Compare commits
21 Commits
master
...
mohr/rtems
Author | SHA1 | Date | |
---|---|---|---|
7426e10f82 | |||
|
123c81777a | ||
6d85fa155e | |||
e6af6200ae | |||
5ca3e83934 | |||
6adabb059a | |||
5d0a5cd201 | |||
adb8483bb0 | |||
fdfdce2fb0 | |||
90efb132d0 | |||
fe9804d922 | |||
a0eae66c35 | |||
e131480d5f | |||
90bafbb6de | |||
47d85fb61c | |||
39dad5f45b | |||
a993c4e0d4 | |||
fe9cc20d00 | |||
552a12a6ad | |||
13639feec6 | |||
654de0f586 |
131
CHANGELOG.md
131
CHANGELOG.md
@ -8,38 +8,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
# [v6.0.0] 2023-02-10
|
# [v6.0.0]
|
||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
|
|
||||||
- Mode Service: Add allowed subservice
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/739
|
|
||||||
- `CService200ModeManagement`: Various bugfixes which lead to now execution complete being generated
|
|
||||||
on mode announcements, duplicate mode reply generated on announce commands, and the mode read
|
|
||||||
subservice not working properly.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/736
|
|
||||||
- Memory leak fixes for the TCP/IP TMTC bridge.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/737
|
|
||||||
- `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval
|
|
||||||
seconds instead of uptime.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726
|
|
||||||
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
|
|
||||||
only the X scaling factor was used.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724
|
|
||||||
- HAL MGM3100 Handler: Z value was previously calculated with bytes of the X value.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/733
|
|
||||||
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
|
|
||||||
to false correctly because the `read` and `write` calls were missing.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/728
|
|
||||||
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
|
|
||||||
of the correct unsegmented flags (0b11) as specified in the standard.
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/727
|
|
||||||
- TC Scheduler Service 11: Add size and CRC check for contained TC.
|
- TC Scheduler Service 11: Add size and CRC check for contained TC.
|
||||||
Bug: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/issues/719
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/720
|
|
||||||
- Only delete health table entry in `HealthHelper` destructor if
|
- Only delete health table entry in `HealthHelper` destructor if
|
||||||
health table was set.
|
health table was set.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710/files
|
||||||
- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator.
|
- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator.
|
||||||
Also properly reset the reply size for successfull transfers and erroneous transfers.
|
Also properly reset the reply size for successfull transfers and erroneous transfers.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
|
||||||
@ -49,82 +25,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- `TcpTmTcServer.cpp`: The server was actually not able to handle
|
- `TcpTmTcServer.cpp`: The server was actually not able to handle
|
||||||
CCSDS packets which were clumped together. This has been fixed now.
|
CCSDS packets which were clumped together. This has been fixed now.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
|
||||||
- `CServiceHealthCommanding`: Add announce all health info implementation
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
|
|
||||||
- various fixes related to linux Unittests and memory leaks
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/715
|
|
||||||
- small fix to allow teardown handling
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/713
|
|
||||||
- fix compiler warning for fixed array list copy ctor
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/704
|
|
||||||
- missing include
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/703
|
|
||||||
- defaultconfig did not build anymore
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/702
|
|
||||||
- hotfix
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/699
|
|
||||||
- small fix for helper
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/698
|
|
||||||
- missing retval conv
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/697
|
|
||||||
- DHB Countdown Bug
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/693
|
|
||||||
- doc corrections
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/687
|
|
||||||
- better error printout
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/686
|
|
||||||
- include correction
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/683
|
|
||||||
- better warning for missing include paths
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/676
|
|
||||||
- Service 11 regression
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/670
|
|
||||||
|
|
||||||
## Added
|
## 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.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
|
||||||
- Add new `UnsignedByteField` class
|
- Add new `UnsignedByteField` class
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
|
||||||
- publish documentation for development and master branch
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/681
|
|
||||||
- Add Linux HAL options
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/663
|
|
||||||
- Expand SerializeIF
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/656
|
|
||||||
- PUS Service 11: Additional Safety Check
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/666
|
|
||||||
- improvements for auto-formatter script
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/665
|
|
||||||
- provide a weak print char impl
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/674
|
|
||||||
|
|
||||||
## Removed
|
|
||||||
|
|
||||||
- now that doc server is up, remove markdown files
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/688
|
|
||||||
- remove bsp specific code
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/679
|
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
- `CService201HealthCommanding` renamed to `CServiceHealthCommanding`,
|
|
||||||
service ID customizable now. `CServiceHealthCommanding` expects configuration struct
|
|
||||||
`HealthServiceCfg` now
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
|
|
||||||
- `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now
|
- `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712
|
||||||
- Moved some container returnvalues to dedicated header and namespace
|
- Moved some container returnvalues to dedicated header and namespace
|
||||||
so they can be used without template specification.
|
to they can be used without template specification.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707
|
||||||
- Remove default secondary header argument for
|
- Remove default secondary header argument for
|
||||||
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
|
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
|
||||||
@ -154,41 +70,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
|
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
|
||||||
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
|
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
|
||||||
|
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
|
||||||
|
interface itself so it can be re-used more easily. Also add new
|
||||||
|
abstract function `bool hasDataAtId(store_address_t storeId) const`.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
|
||||||
- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`:
|
- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`:
|
||||||
- Make functions `const` where it makes sense
|
- Make functions `const` where it makes sense
|
||||||
- Add `const char* getName const` abstract function
|
- Add `const char* getName const` abstract function
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684
|
||||||
- Generic TMTC Bridge Update
|
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/734
|
interface itself so it can be re-used more easily. Also add new
|
||||||
- comment tweak to event parser can read everything
|
abstract function `bool hasDataAtId(store_address_t storeId) const`.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/732
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
|
||||||
- CMakeLists file updates
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/731
|
|
||||||
- improve srv20 error messages
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/723
|
|
||||||
- I2C Linux: remove duplicate printout
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/718
|
|
||||||
- printout handling improvements
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/717
|
|
||||||
- vec getter, reset for content
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/716
|
|
||||||
- updates for source sequence counter
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/714
|
|
||||||
- SP reader getPacketData is const now
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/708
|
|
||||||
- refactoring of serial drivers for linux
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/705
|
|
||||||
- Local Pool Update Remove Add Data Ignore Fault Argument
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/701
|
|
||||||
- Switch to new documentation server
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/694
|
|
||||||
- Windows Tweaks
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/691
|
|
||||||
- Refactor Local Pool API
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/667
|
|
||||||
- group MGM data in local pool vectors
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/664
|
|
||||||
|
|
||||||
|
|
||||||
## CFDP
|
## CFDP
|
||||||
|
|
||||||
@ -208,7 +101,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
implementation without an extra component
|
implementation without an extra component
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
|
||||||
|
|
||||||
# [v5.0.0] 2022-07-25
|
# [v5.0.0] 25.07.2022
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
|
|||||||
# Version file handling #
|
# Version file handling #
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
|
|
||||||
set(FSFW_VERSION_IF_GIT_FAILS 6)
|
set(FSFW_VERSION_IF_GIT_FAILS 5)
|
||||||
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
|
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
|
||||||
set(FSFW_REVISION_IF_GIT_FAILS 0)
|
set(FSFW_REVISION_IF_GIT_FAILS 0)
|
||||||
|
|
||||||
@ -158,7 +158,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 +174,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 +222,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 +247,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 +382,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
|
||||||
|
@ -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 gcc g++ cmake make lcov git valgrind nano iputils-ping python3 pip doxygen graphviz rsync wget qemu-system-arm
|
||||||
|
|
||||||
RUN python3 -m pip install sphinx breathe
|
RUN python3 -m pip install sphinx breathe
|
||||||
|
|
||||||
@ -21,8 +21,12 @@ RUN git clone https://github.com/ETLCPP/etl.git && \
|
|||||||
cmake -B build . && \
|
cmake -B build . && \
|
||||||
cmake --install build/
|
cmake --install 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"
|
||||||
|
|
||||||
#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
105
automation/Jenkinsfile
vendored
@ -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,110 +0,0 @@
|
|||||||
#! /bin/python
|
|
||||||
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import json
|
|
||||||
import urllib.request
|
|
||||||
import re
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="List undocumented PRs"
|
|
||||||
)
|
|
||||||
parser.add_argument("-v", "--version", type=str, required=True)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
match = re.search("([0-9]+\.[0-9]+\.[0-9]+)", args.version)
|
|
||||||
|
|
||||||
if not match:
|
|
||||||
print("invalid version")
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
version = "v" + match.group(1)
|
|
||||||
|
|
||||||
print("looking for milestone for " + version + " ...")
|
|
||||||
|
|
||||||
|
|
||||||
with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/milestones?name=" + version) as milestone_json:
|
|
||||||
milestones = json.load(milestone_json)
|
|
||||||
if (len(milestones) == 0):
|
|
||||||
print("did not find any milestone")
|
|
||||||
exit(1)
|
|
||||||
if (len(milestones) > 1):
|
|
||||||
print("found multiple milestons")
|
|
||||||
milestone_title = milestones[0]['title']
|
|
||||||
milestone = str(milestones[0]['id'])
|
|
||||||
print("Using Milestone \""+ milestone_title + "\" with id " + milestone)
|
|
||||||
|
|
||||||
milestone_prs = []
|
|
||||||
|
|
||||||
page = 1
|
|
||||||
last_count = 1;
|
|
||||||
while last_count != 0:
|
|
||||||
with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/pulls?state=closed&milestone=" + str(milestone) + "&limit=100&page=" + str(page)) as pull_requests_json:
|
|
||||||
pull_requests = json.load(pull_requests_json)
|
|
||||||
for pr in pull_requests:
|
|
||||||
milestone_prs.append({'number': str(pr['number']), 'title' : pr['title']})
|
|
||||||
page += 1
|
|
||||||
last_count = len(pull_requests)
|
|
||||||
|
|
||||||
print("Found " + str(len(milestone_prs)) + " closed PRs in Milestone")
|
|
||||||
|
|
||||||
print("looking for CHANGELOG.md ...")
|
|
||||||
|
|
||||||
path = Path(".")
|
|
||||||
|
|
||||||
files = list(path.glob("CHANGELOG.md"))
|
|
||||||
|
|
||||||
if (len(files) != 1):
|
|
||||||
files = list(path.glob("../CHANGELOG.md"))
|
|
||||||
|
|
||||||
if (len(files) != 1):
|
|
||||||
print("did not find CHANGELOG.md. Run script in either root directory or scripts subfolder.")
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
print("Scanning CHANGELOG.md ...")
|
|
||||||
|
|
||||||
changelog_prs = []
|
|
||||||
|
|
||||||
with open(files[0]) as changelog:
|
|
||||||
line = changelog.readline()
|
|
||||||
while (line):
|
|
||||||
#print("line: " + line)
|
|
||||||
match = re.search("\#.+(v[0-9]+\.[0-9]+\.[0-9]+)", line)
|
|
||||||
if (match):
|
|
||||||
if match.group(1) == version:
|
|
||||||
#print("found version")
|
|
||||||
line = changelog.readline()
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
#print("done with " + match.group(1))
|
|
||||||
break
|
|
||||||
|
|
||||||
match = re.search("PR: https://egit\.irs\.uni-stuttgart\.de/fsfw/fsfw/pulls/([0-9]+)", line)
|
|
||||||
if match:
|
|
||||||
changelog_prs.append(match.group(1))
|
|
||||||
|
|
||||||
line = changelog.readline()
|
|
||||||
|
|
||||||
print("Found " + str(len(changelog_prs)) + " PRs in CHANGELOG.md")
|
|
||||||
|
|
||||||
print("")
|
|
||||||
|
|
||||||
copy_array = changelog_prs.copy()
|
|
||||||
print("PRs in CHANGELOG.md that are not in Milestone:")
|
|
||||||
for pr in milestone_prs:
|
|
||||||
if pr['number'] in copy_array:
|
|
||||||
copy_array.remove(pr['number'])
|
|
||||||
for pr in copy_array:
|
|
||||||
print("https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr)
|
|
||||||
|
|
||||||
print("")
|
|
||||||
|
|
||||||
print("PRs in milestone that are not in CHANGELOG.md:")
|
|
||||||
|
|
||||||
for pr in milestone_prs:
|
|
||||||
if pr['number'] not in changelog_prs:
|
|
||||||
print("- " + pr['title'] + "\n PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr['number'])
|
|
||||||
|
|
||||||
main()
|
|
@ -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(¤tUptime);
|
|
||||||
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(¤tUptime);
|
|
||||||
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(¤tUptime);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
#include "HealthTableIF.h"
|
#include "HealthTableIF.h"
|
||||||
|
|
||||||
class HealthTable : public HealthTableIF, public SystemObject {
|
class HealthTable : public HealthTableIF, public SystemObject {
|
||||||
friend class CServiceHealthCommanding;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit HealthTable(object_id_t objectid);
|
explicit HealthTable(object_id_t objectid);
|
||||||
~HealthTable() override;
|
~HealthTable() override;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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); }
|
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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)
|
||||||
|
@ -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) {
|
||||||
|
@ -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,23 +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;
|
||||||
|
|
||||||
@ -95,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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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,15 @@ 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;
|
|
||||||
}
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
}
|
// }
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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,6 +71,7 @@ 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
|
||||||
@ -107,66 +79,3 @@ timeval Clock::getUptime() {
|
|||||||
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;
|
|
||||||
}
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <rtems/rtems/sem.h>
|
#include <rtems/rtems/sem.h>
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
|
||||||
BinarySemaphore::BinarySemaphore() {}
|
BinarySemaphore::BinarySemaphore() {}
|
||||||
|
|
||||||
BinarySemaphore::~BinarySemaphore() {}
|
BinarySemaphore::~BinarySemaphore() {}
|
||||||
|
@ -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) {
|
|
||||||
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
|
|
||||||
return static_cast<uint32_t>(ticks_per_second);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
ReturnValue_t Clock::setClock(const timeval* time) {
|
||||||
|
TimeOfDay_t time_tod;
|
||||||
|
ReturnValue_t result = convertTimevalToTimeOfDay(time, &time_tod);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
rtems_time_of_day timeRtems;
|
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;
|
|
||||||
}
|
}
|
@ -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;
|
||||||
|
@ -35,10 +35,9 @@ 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:
|
||||||
|
@ -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,
|
||||||
|
@ -9,4 +9,4 @@ target_sources(
|
|||||||
Service17Test.cpp
|
Service17Test.cpp
|
||||||
Service20ParameterManagement.cpp
|
Service20ParameterManagement.cpp
|
||||||
CService200ModeCommanding.cpp
|
CService200ModeCommanding.cpp
|
||||||
CServiceHealthCommanding.cpp)
|
CService201HealthCommanding.cpp)
|
||||||
|
@ -19,8 +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):
|
||||||
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
|
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
default:
|
default:
|
||||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
@ -54,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,
|
||||||
@ -90,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);
|
||||||
|
@ -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,
|
||||||
|
106
src/fsfw/pus/CService201HealthCommanding.cpp
Normal file
106
src/fsfw/pus/CService201HealthCommanding.cpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#include "fsfw/pus/CService201HealthCommanding.h"
|
||||||
|
|
||||||
|
#include "fsfw/health/HasHealthIF.h"
|
||||||
|
#include "fsfw/health/HealthMessage.h"
|
||||||
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
|
#include "fsfw/pus/servicepackets/Service201Packets.h"
|
||||||
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
|
CService201HealthCommanding::CService201HealthCommanding(object_id_t objectId, uint16_t apid,
|
||||||
|
uint8_t serviceId,
|
||||||
|
uint8_t numParallelCommands,
|
||||||
|
uint16_t commandTimeoutSeconds)
|
||||||
|
: CommandingServiceBase(objectId, apid, "PUS 201 Health MGMT", serviceId, numParallelCommands,
|
||||||
|
commandTimeoutSeconds) {}
|
||||||
|
|
||||||
|
ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) {
|
||||||
|
switch (subservice) {
|
||||||
|
case (Subservice::COMMAND_SET_HEALTH):
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH):
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL):
|
||||||
|
return returnvalue::OK;
|
||||||
|
default:
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "Invalid Subservice" << std::endl;
|
||||||
|
#endif
|
||||||
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CService201HealthCommanding::getMessageQueueAndObject(uint8_t subservice,
|
||||||
|
const uint8_t *tcData,
|
||||||
|
size_t tcDataLen,
|
||||||
|
MessageQueueId_t *id,
|
||||||
|
object_id_t *objectId) {
|
||||||
|
if (tcDataLen < sizeof(object_id_t)) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
||||||
|
|
||||||
|
return checkInterfaceAndAcquireMessageQueue(id, objectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
||||||
|
MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
|
||||||
|
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
||||||
|
if (destination == nullptr) {
|
||||||
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*messageQueueToSet = destination->getCommandQueue();
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CService201HealthCommanding::prepareCommand(CommandMessage *message,
|
||||||
|
uint8_t subservice, const uint8_t *tcData,
|
||||||
|
size_t tcDataLen, uint32_t *state,
|
||||||
|
object_id_t objectId) {
|
||||||
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
switch (subservice) {
|
||||||
|
case (Subservice::COMMAND_SET_HEALTH): {
|
||||||
|
HealthSetCommand healthCommand;
|
||||||
|
result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET,
|
||||||
|
healthCommand.getHealth());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
|
||||||
|
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
|
||||||
|
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// Should never happen, subservice was already checked
|
||||||
|
result = returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *reply,
|
||||||
|
Command_t previousCommand, uint32_t *state,
|
||||||
|
CommandMessage *optionalNextCommand,
|
||||||
|
object_id_t objectId, bool *isStep) {
|
||||||
|
Command_t replyId = reply->getCommand();
|
||||||
|
if (replyId == HealthMessage::REPLY_HEALTH_SET) {
|
||||||
|
return EXECUTION_COMPLETE;
|
||||||
|
} else if (replyId == CommandMessageIF::REPLY_REJECTED) {
|
||||||
|
return reply->getReplyRejectedReason();
|
||||||
|
}
|
||||||
|
return CommandingServiceBase::INVALID_REPLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not used for now, health state already reported by event
|
||||||
|
[[maybe_unused]] ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(
|
||||||
|
const CommandMessage *reply) {
|
||||||
|
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
||||||
|
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
||||||
|
HealthSetReply healthSetReply(health, oldHealth);
|
||||||
|
return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
|
||||||
|
}
|
@ -1,26 +1,8 @@
|
|||||||
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
|
|
||||||
#include <fsfw/health/HealthTable.h>
|
|
||||||
|
|
||||||
#include "fsfw/tmtcservices/CommandingServiceBase.h"
|
#include "fsfw/tmtcservices/CommandingServiceBase.h"
|
||||||
|
|
||||||
struct HealthServiceCfg {
|
|
||||||
HealthServiceCfg(object_id_t objectId, uint16_t apid, object_id_t healthTable,
|
|
||||||
uint16_t maxNumHealthInfoPerCycle)
|
|
||||||
: objectId(objectId),
|
|
||||||
apid(apid),
|
|
||||||
table(healthTable),
|
|
||||||
maxNumHealthInfoPerCycle(maxNumHealthInfoPerCycle) {}
|
|
||||||
object_id_t objectId;
|
|
||||||
uint16_t apid;
|
|
||||||
object_id_t table;
|
|
||||||
uint16_t maxNumHealthInfoPerCycle;
|
|
||||||
uint8_t service = 201;
|
|
||||||
uint8_t numParallelCommands = 4;
|
|
||||||
uint16_t commandTimeoutSeconds = 60;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom PUS service to set health of all objects
|
* @brief Custom PUS service to set health of all objects
|
||||||
* implementing hasHealthIF.
|
* implementing hasHealthIF.
|
||||||
@ -35,12 +17,11 @@ struct HealthServiceCfg {
|
|||||||
* child class like this service
|
* child class like this service
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class CServiceHealthCommanding : public CommandingServiceBase {
|
class CService201HealthCommanding : public CommandingServiceBase {
|
||||||
public:
|
public:
|
||||||
CServiceHealthCommanding(HealthServiceCfg args);
|
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
||||||
~CServiceHealthCommanding() override = default;
|
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
|
||||||
|
~CService201HealthCommanding() override = default;
|
||||||
ReturnValue_t initialize() override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* CSB abstract function implementations */
|
/* CSB abstract function implementations */
|
||||||
@ -56,14 +37,7 @@ class CServiceHealthCommanding : public CommandingServiceBase {
|
|||||||
CommandMessage *optionalNextCommand, object_id_t objectId,
|
CommandMessage *optionalNextCommand, object_id_t objectId,
|
||||||
bool *isStep) override;
|
bool *isStep) override;
|
||||||
|
|
||||||
void doPeriodicOperation() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const object_id_t healthTableId;
|
|
||||||
HealthTable *healthTable;
|
|
||||||
uint16_t maxNumHealthInfoPerCycle = 0;
|
|
||||||
bool reportAllHealth = false;
|
|
||||||
ReturnValue_t iterateHealthTable(bool reset);
|
|
||||||
static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
||||||
const object_id_t *objectId);
|
const object_id_t *objectId);
|
||||||
|
|
@ -1,158 +0,0 @@
|
|||||||
#include <fsfw/events/EventManagerIF.h>
|
|
||||||
#include <fsfw/pus/CServiceHealthCommanding.h>
|
|
||||||
|
|
||||||
#include "fsfw/health/HasHealthIF.h"
|
|
||||||
#include "fsfw/health/HealthMessage.h"
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
|
||||||
#include "fsfw/pus/servicepackets/Service201Packets.h"
|
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
|
||||||
|
|
||||||
CServiceHealthCommanding::CServiceHealthCommanding(HealthServiceCfg args)
|
|
||||||
: CommandingServiceBase(args.objectId, args.apid, "PUS 201 Health MGMT", args.service,
|
|
||||||
args.numParallelCommands, args.commandTimeoutSeconds),
|
|
||||||
healthTableId(args.table),
|
|
||||||
maxNumHealthInfoPerCycle(args.maxNumHealthInfoPerCycle) {}
|
|
||||||
|
|
||||||
ReturnValue_t CServiceHealthCommanding::initialize() {
|
|
||||||
ReturnValue_t result = CommandingServiceBase::initialize();
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
healthTable = ObjectManager::instance()->get<HealthTable>(healthTableId);
|
|
||||||
if (healthTable == nullptr) {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CServiceHealthCommanding::isValidSubservice(uint8_t subservice) {
|
|
||||||
switch (subservice) {
|
|
||||||
case (Subservice::COMMAND_SET_HEALTH):
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH):
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL):
|
|
||||||
return returnvalue::OK;
|
|
||||||
default:
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "Invalid Subservice" << std::endl;
|
|
||||||
#endif
|
|
||||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CServiceHealthCommanding::getMessageQueueAndObject(uint8_t subservice,
|
|
||||||
const uint8_t *tcData,
|
|
||||||
size_t tcDataLen,
|
|
||||||
MessageQueueId_t *id,
|
|
||||||
object_id_t *objectId) {
|
|
||||||
switch (subservice) {
|
|
||||||
case (Subservice::COMMAND_SET_HEALTH):
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
|
|
||||||
if (tcDataLen < sizeof(object_id_t)) {
|
|
||||||
return CommandingServiceBase::INVALID_TC;
|
|
||||||
}
|
|
||||||
SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
|
||||||
|
|
||||||
return checkInterfaceAndAcquireMessageQueue(id, objectId);
|
|
||||||
}
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CServiceHealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
|
||||||
MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
|
|
||||||
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
|
||||||
if (destination == nullptr) {
|
|
||||||
return CommandingServiceBase::INVALID_OBJECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
*messageQueueToSet = destination->getCommandQueue();
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
|
|
||||||
const uint8_t *tcData, size_t tcDataLen,
|
|
||||||
uint32_t *state, object_id_t objectId) {
|
|
||||||
ReturnValue_t result = returnvalue::OK;
|
|
||||||
switch (subservice) {
|
|
||||||
case (Subservice::COMMAND_SET_HEALTH): {
|
|
||||||
HealthSetCommand healthCommand;
|
|
||||||
result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET,
|
|
||||||
healthCommand.getHealth());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
|
|
||||||
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
|
|
||||||
ReturnValue_t result = iterateHealthTable(true);
|
|
||||||
if (result == returnvalue::OK) {
|
|
||||||
reportAllHealth = true;
|
|
||||||
return EXECUTION_COMPLETE;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
// Should never happen, subservice was already checked
|
|
||||||
result = returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CServiceHealthCommanding::handleReply(const CommandMessage *reply,
|
|
||||||
Command_t previousCommand, uint32_t *state,
|
|
||||||
CommandMessage *optionalNextCommand,
|
|
||||||
object_id_t objectId, bool *isStep) {
|
|
||||||
Command_t replyId = reply->getCommand();
|
|
||||||
if (replyId == HealthMessage::REPLY_HEALTH_SET) {
|
|
||||||
return EXECUTION_COMPLETE;
|
|
||||||
} else if (replyId == CommandMessageIF::REPLY_REJECTED) {
|
|
||||||
return reply->getReplyRejectedReason();
|
|
||||||
}
|
|
||||||
return CommandingServiceBase::INVALID_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CServiceHealthCommanding::doPeriodicOperation() {
|
|
||||||
if (reportAllHealth) {
|
|
||||||
for (uint8_t i = 0; i < maxNumHealthInfoPerCycle; i++) {
|
|
||||||
ReturnValue_t result = iterateHealthTable(false);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
reportAllHealth = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not used for now, health state already reported by event
|
|
||||||
[[maybe_unused]] ReturnValue_t CServiceHealthCommanding::prepareHealthSetReply(
|
|
||||||
const CommandMessage *reply) {
|
|
||||||
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
|
||||||
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
|
||||||
HealthSetReply healthSetReply(health, oldHealth);
|
|
||||||
return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CServiceHealthCommanding::iterateHealthTable(bool reset) {
|
|
||||||
std::pair<object_id_t, HasHealthIF::HealthState> pair;
|
|
||||||
|
|
||||||
ReturnValue_t result = healthTable->iterate(&pair, reset);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
EventManagerIF::triggerEvent(pair.first, HasHealthIF::HEALTH_INFO, pair.second, pair.second);
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -198,10 +198,9 @@ void Heater::setSwitch(uint8_t number, ReturnValue_t state, uint32_t* uptimeOfSw
|
|||||||
} 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(¤tUptime);
|
|
||||||
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())) {
|
||||||
|
@ -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 =
|
||||||
|
@ -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,
|
||||||
|
@ -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.
|
||||||
|
@ -14,8 +14,10 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
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 +28,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 +55,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 +68,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 +79,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 +96,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
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
#include "fsfw/ipc/MutexGuard.h"
|
#include "fsfw/ipc/MutexGuard.h"
|
||||||
#include "fsfw/timemanager/Clock.h"
|
#include "fsfw/timemanager/Clock.h"
|
||||||
@ -53,34 +54,74 @@ 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
|
|
||||||
// this implementation
|
|
||||||
ReturnValue_t result = checkOrCreateClockMutex();
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
// 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
|
#ifdef PLATFORM_WIN
|
||||||
time_t time;
|
errno_t result = gmtime_s(&time_tm, &from->tv_sec);
|
||||||
time = from->tv_sec;
|
if (result != 0) {
|
||||||
timeInfo = gmtime(&time);
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
#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;
|
||||||
|
|
||||||
|
// Windows:
|
||||||
|
// time_t seconds = _mkgmtime(&time_tm);
|
||||||
|
// Glibc:
|
||||||
|
// time_t seconds = timegm(&time_tm);
|
||||||
|
// Portable (?)
|
||||||
|
char* tz;
|
||||||
|
tz = getenv("TZ");
|
||||||
|
setenv("TZ", "", 1);
|
||||||
|
tzset();
|
||||||
|
time_t seconds = mktime(&time_tm);
|
||||||
|
if (tz)
|
||||||
|
setenv("TZ", tz, 1);
|
||||||
|
else
|
||||||
|
unsetenv("TZ");
|
||||||
|
tzset();
|
||||||
|
to->tv_sec = seconds;
|
||||||
|
to->tv_usec = from->usecond;
|
||||||
|
|
||||||
|
if (seconds == (time_t) -1) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 +135,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;
|
||||||
|
}
|
@ -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 {
|
||||||
@ -39,7 +39,5 @@ uint32_t Countdown::getRemainingMillis() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Countdown::getCurrentTime() const {
|
uint32_t Countdown::getCurrentTime() const {
|
||||||
uint32_t currentTime;
|
return Clock::getUptime_ms();
|
||||||
Clock::getUptime(¤tTime);
|
|
||||||
return currentTime;
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
|
||||||
#include "fsfw/platform.h"
|
#include "fsfw/platform.h"
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
@ -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_ */
|
||||||
|
@ -325,12 +325,12 @@ 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;
|
||||||
float fieldStrengthY = fieldStrengthRawY * scaleFactorY;
|
float fieldStrengthY = fieldStrengthRawY * scaleFactorX;
|
||||||
float fieldStrengthZ = fieldStrengthRawZ * scaleFactorZ;
|
float fieldStrengthZ = fieldStrengthRawZ * scaleFactorX;
|
||||||
|
|
||||||
if (periodicPrintout) {
|
if (periodicPrintout) {
|
||||||
if (debugDivider.checkAndIncrement()) {
|
if (debugDivider.checkAndIncrement()) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
IF(NOT FSFW_OSAL MATCHES "rtems")
|
||||||
add_subdirectory(hal)
|
add_subdirectory(hal)
|
||||||
|
ENDIF()
|
||||||
add_subdirectory(internalerror)
|
add_subdirectory(internalerror)
|
||||||
add_subdirectory(devicehandler)
|
add_subdirectory(devicehandler)
|
||||||
add_subdirectory(tmtcservices)
|
add_subdirectory(tmtcservices)
|
||||||
|
@ -10,16 +10,120 @@
|
|||||||
|
|
||||||
#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();
|
||||||
|
@ -1,2 +1,5 @@
|
|||||||
target_sources(${FSFW_TEST_TGT} PRIVATE testMq.cpp TestSemaphore.cpp
|
target_sources(${FSFW_TEST_TGT} PRIVATE testMq.cpp TestClock.cpp)
|
||||||
TestClock.cpp)
|
|
||||||
|
if(FSFW_OSAL MATCHES "linux" OR FSFW_OSAL MATCHES "freertos")
|
||||||
|
target_sources(${FSFW_TEST_TGT} PRIVATE TestSemaphore.cpp)
|
||||||
|
endif()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <fsfw/globalfunctions/timevalOperations.h>
|
#include <fsfw/globalfunctions/timevalOperations.h>
|
||||||
#include <fsfw/timemanager/Clock.h>
|
#include <fsfw/timemanager/Clock.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <catch2/catch_approx.hpp>
|
#include <catch2/catch_approx.hpp>
|
||||||
@ -7,6 +8,8 @@
|
|||||||
|
|
||||||
#include "CatchDefinitions.h"
|
#include "CatchDefinitions.h"
|
||||||
|
|
||||||
|
//TODO setClock()
|
||||||
|
|
||||||
TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") {
|
TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") {
|
||||||
SECTION("Test getClock") {
|
SECTION("Test getClock") {
|
||||||
timeval time;
|
timeval time;
|
||||||
@ -21,7 +24,7 @@ TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") {
|
|||||||
// We require timeOfDayAsTimeval to be larger than time as it
|
// We require timeOfDayAsTimeval to be larger than time as it
|
||||||
// was request a few ns later
|
// was request a few ns later
|
||||||
double difference = timevalOperations::toDouble(timeOfDayAsTimeval - time);
|
double difference = timevalOperations::toDouble(timeOfDayAsTimeval - time);
|
||||||
CHECK(difference >= 0.0);
|
CHECK(difference >= 0);
|
||||||
CHECK(difference <= 0.005);
|
CHECK(difference <= 0.005);
|
||||||
|
|
||||||
// Conversion in the other direction
|
// Conversion in the other direction
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
// binary semaphores currently only supported on linux
|
|
||||||
#ifdef FSFW_OSAL_LINUX
|
|
||||||
|
|
||||||
TEST_CASE("Binary Semaphore Test", "[BinSemaphore]") {
|
TEST_CASE("Binary Semaphore Test", "[BinSemaphore]") {
|
||||||
// perform set-up here
|
// perform set-up here
|
||||||
@ -34,5 +32,3 @@ TEST_CASE("Binary Semaphore Test", "[BinSemaphore]") {
|
|||||||
TEST_CASE("Counting Semaphore Test", "[CountingSemaph]") {
|
TEST_CASE("Counting Semaphore Test", "[CountingSemaph]") {
|
||||||
SECTION("Simple Test") {}
|
SECTION("Simple Test") {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace addresses {
|
namespace addresses {
|
||||||
/* Logical addresses have uint32_t datatype */
|
/* Logical addresses have uint32_t datatype */
|
||||||
enum LogicAddress : address_t {};
|
enum logicalAddresses : address_t {};
|
||||||
} // namespace addresses
|
} // namespace addresses
|
||||||
|
|
||||||
#endif /* CONFIG_DEVICES_LOGICALADDRESSES_H_ */
|
#endif /* CONFIG_DEVICES_LOGICALADDRESSES_H_ */
|
||||||
|
102
unittests/testcfg/freertos/FreeRTOSConfig.h
Normal file
102
unittests/testcfg/freertos/FreeRTOSConfig.h
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#ifndef FREERTOS_CONFIG_H
|
||||||
|
#define FREERTOS_CONFIG_H
|
||||||
|
|
||||||
|
#define configUSE_PREEMPTION 1
|
||||||
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
|
||||||
|
#define configUSE_TICKLESS_IDLE 0
|
||||||
|
#define configTICK_RATE_HZ 1000
|
||||||
|
#define configMAX_PRIORITIES 5
|
||||||
|
#define configMINIMAL_STACK_SIZE ((unsigned short)PTHREAD_STACK_MIN)
|
||||||
|
#define configMAX_TASK_NAME_LEN 16
|
||||||
|
#define configUSE_16_BIT_TICKS 0
|
||||||
|
#define configIDLE_SHOULD_YIELD 1
|
||||||
|
#define configUSE_TASK_NOTIFICATIONS 1
|
||||||
|
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 3
|
||||||
|
#define configUSE_MUTEXES 1
|
||||||
|
#define configUSE_RECURSIVE_MUTEXES 0
|
||||||
|
#define configUSE_COUNTING_SEMAPHORES 1
|
||||||
|
#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */
|
||||||
|
#define configQUEUE_REGISTRY_SIZE 20
|
||||||
|
#define configUSE_QUEUE_SETS 0
|
||||||
|
#define configUSE_TIME_SLICING 0
|
||||||
|
#define configUSE_NEWLIB_REENTRANT 0
|
||||||
|
#define configENABLE_BACKWARD_COMPATIBILITY 1
|
||||||
|
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
|
||||||
|
#define configUSE_MINI_LIST_ITEM 1
|
||||||
|
#define configSTACK_DEPTH_TYPE uint16_t
|
||||||
|
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
|
||||||
|
#define configHEAP_CLEAR_MEMORY_ON_FREE 1
|
||||||
|
|
||||||
|
/* Memory allocation related definitions. */
|
||||||
|
#define configSUPPORT_STATIC_ALLOCATION 0
|
||||||
|
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||||
|
#define configTOTAL_HEAP_SIZE ((size_t)(1024 * 1024))
|
||||||
|
#define configAPPLICATION_ALLOCATED_HEAP 1
|
||||||
|
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
|
||||||
|
|
||||||
|
/* Hook function related definitions. */
|
||||||
|
#define configUSE_IDLE_HOOK 0
|
||||||
|
#define configUSE_TICK_HOOK 0
|
||||||
|
#define configCHECK_FOR_STACK_OVERFLOW 0
|
||||||
|
#define configUSE_MALLOC_FAILED_HOOK 0
|
||||||
|
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
|
||||||
|
#define configUSE_SB_COMPLETED_CALLBACK 0
|
||||||
|
|
||||||
|
/* Run time and task stats gathering related definitions. */
|
||||||
|
#define configGENERATE_RUN_TIME_STATS 0
|
||||||
|
#define configUSE_TRACE_FACILITY 0
|
||||||
|
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
|
||||||
|
|
||||||
|
/* Co-routine related definitions. */
|
||||||
|
#define configUSE_CO_ROUTINES 0
|
||||||
|
#define configMAX_CO_ROUTINE_PRIORITIES 1
|
||||||
|
|
||||||
|
/* Software timer related definitions. */
|
||||||
|
#define configUSE_TIMERS 1
|
||||||
|
#define configTIMER_TASK_PRIORITY 3
|
||||||
|
#define configTIMER_QUEUE_LENGTH 10
|
||||||
|
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
|
||||||
|
|
||||||
|
/* Interrupt nesting behaviour configuration. */
|
||||||
|
#define configKERNEL_INTERRUPT_PRIORITY [dependent of processor]
|
||||||
|
#define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application]
|
||||||
|
#define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application]
|
||||||
|
|
||||||
|
/* Define to trap errors during development. */
|
||||||
|
//#define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )
|
||||||
|
|
||||||
|
/* FreeRTOS MPU specific definitions. */
|
||||||
|
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
|
||||||
|
#define configTOTAL_MPU_REGIONS 8 /* Default value. */
|
||||||
|
#define configTEX_S_C_B_FLASH 0x07UL /* Default value. */
|
||||||
|
#define configTEX_S_C_B_SRAM 0x07UL /* Default value. */
|
||||||
|
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 1
|
||||||
|
#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1
|
||||||
|
#define configENABLE_ERRATA_837070_WORKAROUND 1
|
||||||
|
|
||||||
|
/* ARMv8-M secure side port related definitions. */
|
||||||
|
#define secureconfigMAX_SECURE_CONTEXTS 5
|
||||||
|
|
||||||
|
/* Optional functions - most linkers will remove unused functions anyway. */
|
||||||
|
#define INCLUDE_vTaskPrioritySet 1
|
||||||
|
#define INCLUDE_uxTaskPriorityGet 1
|
||||||
|
#define INCLUDE_vTaskDelete 1
|
||||||
|
#define INCLUDE_vTaskSuspend 1
|
||||||
|
#define INCLUDE_xResumeFromISR 1
|
||||||
|
#define INCLUDE_vTaskDelayUntil 1
|
||||||
|
#define INCLUDE_vTaskDelay 1
|
||||||
|
#define INCLUDE_xTaskGetSchedulerState 1
|
||||||
|
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||||
|
#define INCLUDE_uxTaskGetStackHighWaterMark 0
|
||||||
|
#define INCLUDE_uxTaskGetStackHighWaterMark2 0
|
||||||
|
#define INCLUDE_xTaskGetIdleTaskHandle 0
|
||||||
|
#define INCLUDE_eTaskGetState 0
|
||||||
|
#define INCLUDE_xEventGroupSetBitFromISR 1
|
||||||
|
#define INCLUDE_xTimerPendFunctionCall 0
|
||||||
|
#define INCLUDE_xTaskAbortDelay 0
|
||||||
|
#define INCLUDE_xTaskGetHandle 0
|
||||||
|
#define INCLUDE_xTaskResumeFromISR 1
|
||||||
|
|
||||||
|
/* A header file that defines trace macro can be included here. */
|
||||||
|
|
||||||
|
#endif /* FREERTOS_CONFIG_H */
|
@ -0,0 +1,3 @@
|
|||||||
|
add_compile_options("-mcpu=cortex-a72" "-I/opt/rtems/6/aarch64-rtems6/a72_lp64_qemu/lib/include")
|
||||||
|
|
||||||
|
add_link_options("-B/opt/rtems/6/aarch64-rtems6/a72_lp64_qemu/lib" "-qrtems")
|
36
unittests/testcfg/rtems/cmake/aarch64-rtems6-toolchain.cmake
Normal file
36
unittests/testcfg/rtems/cmake/aarch64-rtems6-toolchain.cmake
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
## the name of the target operating system
|
||||||
|
set(CMAKE_SYSTEM_NAME a72_lp64_qemu)
|
||||||
|
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR a72)
|
||||||
|
|
||||||
|
# which compilers to use for C and C++
|
||||||
|
set(CMAKE_C_COMPILER aarch64-rtems6-gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER aarch64-rtems6-g++)
|
||||||
|
|
||||||
|
# built in tests fail
|
||||||
|
set(CMAKE_C_COMPILER_WORKS 1)
|
||||||
|
set(CMAKE_CXX_COMPILER_WORKS 1)
|
||||||
|
|
||||||
|
# adjust the default behavior of the FIND_XXX() commands:
|
||||||
|
# search programs in the host environment
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
|
||||||
|
|
||||||
|
# search headers and libraries in the target environment
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||||
|
|
||||||
|
# ignore host installed libraries
|
||||||
|
# makes find_package() ignore the <package>Config.cmake files
|
||||||
|
set(CMAKE_IGNORE_PATH /usr/local)
|
||||||
|
|
||||||
|
|
||||||
|
# supress errors
|
||||||
|
add_compile_definitions("__STDC_VERSION__")
|
||||||
|
|
||||||
|
# make newlib behave like glib with an intercepted cmath
|
||||||
|
add_compile_options("-I${CMAKE_SOURCE_DIR}/unittests/testcfg/rtems/include")
|
||||||
|
|
||||||
|
# we supply an a72_lp64_qemu.cmake there
|
||||||
|
list(APPEND CMAKE_MODULE_PATH
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/unittests/testcfg/rtems/cmake")
|
39
unittests/testcfg/rtems/include/cmath
Normal file
39
unittests/testcfg/rtems/include/cmath
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include_next <cmath>
|
||||||
|
|
||||||
|
extern "C++"
|
||||||
|
{
|
||||||
|
namespace std _GLIBCXX_VISIBILITY(default)
|
||||||
|
{
|
||||||
|
|
||||||
|
#undef lround
|
||||||
|
#undef erfc
|
||||||
|
#undef round
|
||||||
|
|
||||||
|
|
||||||
|
using ::lround;
|
||||||
|
|
||||||
|
long
|
||||||
|
lround(float __x);
|
||||||
|
|
||||||
|
constexpr long
|
||||||
|
lround(long double __x);
|
||||||
|
|
||||||
|
using ::erfc;
|
||||||
|
|
||||||
|
constexpr float
|
||||||
|
erfc(float __x);
|
||||||
|
|
||||||
|
constexpr long double
|
||||||
|
erfc(long double __x);
|
||||||
|
|
||||||
|
constexpr float
|
||||||
|
round(float __x);
|
||||||
|
|
||||||
|
using ::round;
|
||||||
|
|
||||||
|
constexpr long double
|
||||||
|
round(long double __x);
|
||||||
|
}
|
||||||
|
}
|
32
unittests/testcfg/rtems/include/rtemsConfig.h
Normal file
32
unittests/testcfg/rtems/include/rtemsConfig.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include <rtems/extension.h>
|
||||||
|
#include <rtems/bspIo.h>
|
||||||
|
void user_handle_fatal(Internal_errors_Source source, bool internal, Internal_errors_t error_code);
|
||||||
|
|
||||||
|
#define RTEMS_USE_UNLIMITED_OBJECTS_ALLOCATION 0
|
||||||
|
|
||||||
|
#define CONFIGURE_MICROSECONDS_PER_TICK 1000
|
||||||
|
|
||||||
|
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
|
||||||
|
|
||||||
|
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
|
||||||
|
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
|
||||||
|
|
||||||
|
#define CONFIGURE_MAXIMUM_TASKS 20
|
||||||
|
#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 30
|
||||||
|
#define CONFIGURE_MAXIMUM_SEMAPHORES 20
|
||||||
|
#define CONFIGURE_MAXIMUM_TIMERS 10
|
||||||
|
//! Required for Rate-Monotonic Scheduling (RMS)
|
||||||
|
#define CONFIGURE_MAXIMUM_PERIODS 15
|
||||||
|
#define CONFIGURE_INIT_TASK_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 6)
|
||||||
|
//! Around 41 kB extra task stack for now.
|
||||||
|
#define CONFIGURE_EXTRA_TASK_STACKS (10 * RTEMS_MINIMUM_STACK_SIZE)
|
||||||
|
|
||||||
|
#define CONFIGURE_INITIAL_EXTENSIONS { NULL, NULL, NULL, NULL, NULL, NULL, NULL, user_handle_fatal, NULL }
|
||||||
|
|
||||||
|
#define CONFIGURE_INIT
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/confdefs.h>
|
Loading…
Reference in New Issue
Block a user