Update from upstream #85
14
CHANGELOG.md
14
CHANGELOG.md
@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
|
- Bump C++ required version to C++17. Every project which uses the FSFW and every modern
|
||||||
|
compiler supports it
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622
|
||||||
- HAL Linux SPI: Set the Clock Default State when setting new SPI speed
|
- HAL Linux SPI: Set the Clock Default State when setting new SPI speed
|
||||||
and mode
|
and mode
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
|
||||||
@ -28,6 +31,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
creation call. It allows passing context information and an arbitrary user argument into
|
creation call. It allows passing context information and an arbitrary user argument into
|
||||||
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
|
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
|
||||||
|
- Clock:
|
||||||
|
- `timeval` to `TimeOfDay_t`
|
||||||
|
- Added Mutex for gmtime calls: (compare http://www.opengate.at/blog/2020/01/timeless/)
|
||||||
|
- Moved the statics used by Clock in ClockCommon.cpp to this file
|
||||||
|
- Better check for leap seconds
|
||||||
|
- Added Unittests for Clock (only getter)
|
||||||
|
|
||||||
## Removed
|
## Removed
|
||||||
|
|
||||||
@ -46,8 +55,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
- Move some CMake directives further up top so they are not ignored
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/621
|
||||||
- Small bugfix in STM32 HAL for SPI
|
- Small bugfix in STM32 HAL for SPI
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/599
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/599
|
||||||
|
- HAL GPIO: Improved error checking in `LinuxLibgpioIF::configureGpios(...)`. If a GPIO
|
||||||
|
configuration fails, the function will exit prematurely with a dedicated error code
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/602
|
||||||
|
|
||||||
# [v4.0.0]
|
# [v4.0.0]
|
||||||
|
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
|
set(LIB_FSFW_NAME fsfw)
|
||||||
|
project(${LIB_FSFW_NAME})
|
||||||
|
|
||||||
|
if(NOT CMAKE_CXX_STANDARD)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
elseif(${CMAKE_CXX_STANDARD} LESS 17)
|
||||||
|
message(FATAL_ERROR "Compiling the FSFW requires a minimum of C++17 support")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(FSFW_VERSION 4)
|
set(FSFW_VERSION 4)
|
||||||
set(FSFW_SUBVERSION 0)
|
set(FSFW_SUBVERSION 0)
|
||||||
set(FSFW_REVISION 0)
|
set(FSFW_REVISION 0)
|
||||||
@ -10,14 +20,15 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
|||||||
set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING
|
set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING
|
||||||
"ETL library major version requirement"
|
"ETL library major version requirement"
|
||||||
)
|
)
|
||||||
set(FSFW_ETL_LIB_VERSION ${FSFW_ETL_LIB_MAJOR_VERSION}.27.2 CACHE STRING
|
set(FSFW_ETL_LIB_VERSION ${FSFW_ETL_LIB_MAJOR_VERSION}.27.3 CACHE STRING
|
||||||
"ETL library exact version requirement"
|
"ETL library exact version requirement"
|
||||||
)
|
)
|
||||||
|
set(FSFW_ETL_LINK_TARGET etl::etl)
|
||||||
|
|
||||||
set(FSFW_CATCH2_LIB_MAJOR_VERSION 3 CACHE STRING
|
set(FSFW_CATCH2_LIB_MAJOR_VERSION 3 CACHE STRING
|
||||||
"Catch2 library major version requirement"
|
"Catch2 library major version requirement"
|
||||||
)
|
)
|
||||||
set(FSFW_CATCH2_LIB_VERSION v${FSFW_CATCH2_LIB_MAJOR_VERSION}.0.0-preview4 CACHE STRING
|
set(FSFW_CATCH2_LIB_VERSION v${FSFW_CATCH2_LIB_MAJOR_VERSION}.0.0-preview5 CACHE STRING
|
||||||
"Catch2 library exact version requirement"
|
"Catch2 library exact version requirement"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -54,11 +65,10 @@ option(FSFW_ADD_TMSTORAGE "Compile with tm storage components" OFF)
|
|||||||
# Contrib sources
|
# Contrib sources
|
||||||
option(FSFW_ADD_SGP4_PROPAGATOR "Add SGP4 propagator code" OFF)
|
option(FSFW_ADD_SGP4_PROPAGATOR "Add SGP4 propagator code" OFF)
|
||||||
|
|
||||||
set(LIB_FSFW_NAME fsfw)
|
|
||||||
set(FSFW_TEST_TGT fsfw-tests)
|
set(FSFW_TEST_TGT fsfw-tests)
|
||||||
set(FSFW_DUMMY_TGT fsfw-dummy)
|
set(FSFW_DUMMY_TGT fsfw-dummy)
|
||||||
|
|
||||||
project(${LIB_FSFW_NAME})
|
|
||||||
add_library(${LIB_FSFW_NAME})
|
add_library(${LIB_FSFW_NAME})
|
||||||
|
|
||||||
if(FSFW_BUILD_UNITTESTS)
|
if(FSFW_BUILD_UNITTESTS)
|
||||||
@ -76,9 +86,7 @@ if(FSFW_BUILD_UNITTESTS)
|
|||||||
GIT_TAG ${FSFW_CATCH2_LIB_VERSION}
|
GIT_TAG ${FSFW_CATCH2_LIB_VERSION}
|
||||||
)
|
)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(Catch2)
|
list(APPEND FSFW_FETCH_CONTENT_TARGETS Catch2)
|
||||||
#fixes regression -preview4, to be confirmed in later releases
|
|
||||||
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg)
|
set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg)
|
||||||
@ -123,7 +131,22 @@ if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
|||||||
GIT_TAG ${FSFW_ETL_LIB_VERSION}
|
GIT_TAG ${FSFW_ETL_LIB_VERSION}
|
||||||
)
|
)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(etl)
|
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_ETL_LIB_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# The documentation for FetchContent recommends declaring all the dependencies
|
||||||
|
# before making them available. We make all declared dependency available here
|
||||||
|
# after their declaration
|
||||||
|
if(FSFW_FETCH_CONTENT_TARGETS)
|
||||||
|
FetchContent_MakeAvailable(${FSFW_FETCH_CONTENT_TARGETS})
|
||||||
|
if(TARGET ${FSFW_ETL_LIB_NAME})
|
||||||
|
add_library(${FSFW_ETL_LINK_TARGET} ALIAS ${FSFW_ETL_LIB_NAME})
|
||||||
|
endif()
|
||||||
|
if(TARGET Catch2)
|
||||||
|
# Fixes regression -preview4, to be confirmed in later releases
|
||||||
|
# Related GitHub issue: https://github.com/catchorg/Catch2/issues/2417
|
||||||
|
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(FSFW_CORE_INC_PATH "inc")
|
set(FSFW_CORE_INC_PATH "inc")
|
||||||
@ -138,12 +161,6 @@ target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
|||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT CMAKE_CXX_STANDARD)
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
|
||||||
elseif(${CMAKE_CXX_STANDARD} LESS 11)
|
|
||||||
message(FATAL_ERROR "Compiling the FSFW requires a minimum of C++11 support")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Backwards comptability
|
# Backwards comptability
|
||||||
if(OS_FSFW AND NOT FSFW_OSAL)
|
if(OS_FSFW AND NOT FSFW_OSAL)
|
||||||
@ -387,7 +404,7 @@ target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||||
${FSFW_ETL_LIB_NAME}
|
${FSFW_ETL_LINK_TARGET}
|
||||||
${FSFW_ADDITIONAL_LINK_LIBS}
|
${FSFW_ADDITIONAL_LINK_LIBS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -6,3 +6,9 @@ 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
|
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping
|
||||||
|
|
||||||
|
RUN git clone https://github.com/catchorg/Catch2.git && \
|
||||||
|
cd Catch2 && \
|
||||||
|
git checkout v3.0.0-preview5 && \
|
||||||
|
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
|
||||||
|
cmake --build build/ --target install
|
||||||
|
2
automation/Jenkinsfile
vendored
2
automation/Jenkinsfile
vendored
@ -3,7 +3,7 @@ pipeline {
|
|||||||
BUILDDIR = 'build-tests'
|
BUILDDIR = 'build-tests'
|
||||||
}
|
}
|
||||||
agent {
|
agent {
|
||||||
docker { image 'fsfw-ci:d1'}
|
docker { image 'fsfw-ci:d2'}
|
||||||
}
|
}
|
||||||
stages {
|
stages {
|
||||||
stage('Clean') {
|
stage('Clean') {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include "MgmLIS3MDLHandler.h"
|
#include "MgmLIS3MDLHandler.h"
|
||||||
|
|
||||||
#include "fsfw/datapool/PoolReadGuard.h"
|
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "fsfw/datapool/PoolReadGuard.h"
|
||||||
|
|
||||||
MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCommunication,
|
MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCommunication,
|
||||||
CookieIF *comCookie, uint32_t transitionDelay)
|
CookieIF *comCookie, uint32_t transitionDelay)
|
||||||
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
|
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
|
||||||
|
@ -12,9 +12,14 @@ if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
|
|||||||
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
|
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
|
||||||
add_subdirectory(gpio)
|
add_subdirectory(gpio)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(spi)
|
|
||||||
add_subdirectory(i2c)
|
|
||||||
add_subdirectory(uart)
|
add_subdirectory(uart)
|
||||||
|
# Adding those does not really make sense on Apple systems which
|
||||||
|
# are generally host systems. It won't even compile as the headers
|
||||||
|
# are missing
|
||||||
|
if(NOT APPLE)
|
||||||
|
add_subdirectory(i2c)
|
||||||
|
add_subdirectory(spi)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(uio)
|
add_subdirectory(uio)
|
||||||
|
@ -44,6 +44,7 @@ ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
||||||
|
ReturnValue_t result = RETURN_OK;
|
||||||
for (auto& gpioConfig : mapToAdd) {
|
for (auto& gpioConfig : mapToAdd) {
|
||||||
auto& gpioType = gpioConfig.second->gpioType;
|
auto& gpioType = gpioConfig.second->gpioType;
|
||||||
switch (gpioType) {
|
switch (gpioType) {
|
||||||
@ -55,7 +56,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
|||||||
if (regularGpio == nullptr) {
|
if (regularGpio == nullptr) {
|
||||||
return GPIO_INVALID_INSTANCE;
|
return GPIO_INVALID_INSTANCE;
|
||||||
}
|
}
|
||||||
configureGpioByChip(gpioConfig.first, *regularGpio);
|
result = configureGpioByChip(gpioConfig.first, *regularGpio);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): {
|
case (gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): {
|
||||||
@ -63,7 +64,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
|||||||
if (regularGpio == nullptr) {
|
if (regularGpio == nullptr) {
|
||||||
return GPIO_INVALID_INSTANCE;
|
return GPIO_INVALID_INSTANCE;
|
||||||
}
|
}
|
||||||
configureGpioByLabel(gpioConfig.first, *regularGpio);
|
result = configureGpioByLabel(gpioConfig.first, *regularGpio);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): {
|
case (gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): {
|
||||||
@ -71,7 +72,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
|||||||
if (regularGpio == nullptr) {
|
if (regularGpio == nullptr) {
|
||||||
return GPIO_INVALID_INSTANCE;
|
return GPIO_INVALID_INSTANCE;
|
||||||
}
|
}
|
||||||
configureGpioByLineName(gpioConfig.first, *regularGpio);
|
result = configureGpioByLineName(gpioConfig.first, *regularGpio);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (gpio::GpioTypes::CALLBACK): {
|
case (gpio::GpioTypes::CALLBACK): {
|
||||||
@ -83,8 +84,11 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
|||||||
gpioCallback->initValue, gpioCallback->callbackArgs);
|
gpioCallback->initValue, gpioCallback->callbackArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (result != RETURN_OK) {
|
||||||
|
return GPIO_INIT_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return RETURN_OK;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId,
|
ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId,
|
||||||
|
@ -29,6 +29,8 @@ class LinuxLibgpioIF : public GpioIF, public SystemObject {
|
|||||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4);
|
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4);
|
||||||
static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED =
|
static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED =
|
||||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5);
|
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5);
|
||||||
|
static constexpr ReturnValue_t GPIO_INIT_FAILED =
|
||||||
|
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 6);
|
||||||
|
|
||||||
LinuxLibgpioIF(object_id_t objectId);
|
LinuxLibgpioIF(object_id_t objectId);
|
||||||
virtual ~LinuxLibgpioIF();
|
virtual ~LinuxLibgpioIF();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "fsfw_hal/linux/spi/SpiCookie.h"
|
#include "SpiCookie.h"
|
||||||
|
|
||||||
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
|
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
|
||||||
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed)
|
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed)
|
||||||
|
@ -265,6 +265,7 @@ void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCooki
|
|||||||
cfsetispeed(options, B230400);
|
cfsetispeed(options, B230400);
|
||||||
cfsetospeed(options, B230400);
|
cfsetospeed(options, B230400);
|
||||||
break;
|
break;
|
||||||
|
#ifndef __APPLE__
|
||||||
case UartBaudRate::RATE_460800:
|
case UartBaudRate::RATE_460800:
|
||||||
cfsetispeed(options, B460800);
|
cfsetispeed(options, B460800);
|
||||||
cfsetospeed(options, B460800);
|
cfsetospeed(options, B460800);
|
||||||
@ -313,6 +314,7 @@ void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCooki
|
|||||||
cfsetispeed(options, B4000000);
|
cfsetispeed(options, B4000000);
|
||||||
cfsetospeed(options, B4000000);
|
cfsetospeed(options, B4000000);
|
||||||
break;
|
break;
|
||||||
|
#endif // ! __APPLE__
|
||||||
default:
|
default:
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
|
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
|
||||||
|
@ -24,9 +24,7 @@ void UartCookie::setParityEven() { parity = Parity::EVEN; }
|
|||||||
|
|
||||||
Parity UartCookie::getParity() const { return parity; }
|
Parity UartCookie::getParity() const { return parity; }
|
||||||
|
|
||||||
void UartCookie::setBitsPerWord(BitsPerWord bitsPerWord_) {
|
void UartCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; }
|
||||||
bitsPerWord = bitsPerWord_;
|
|
||||||
}
|
|
||||||
|
|
||||||
BitsPerWord UartCookie::getBitsPerWord() const { return bitsPerWord; }
|
BitsPerWord UartCookie::getBitsPerWord() const { return bitsPerWord; }
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ class HeaderSerializer : public SerializeIF, public PduHeaderIF {
|
|||||||
cfdp::WidthInBytes getLenEntityIds() const override;
|
cfdp::WidthInBytes getLenEntityIds() const override;
|
||||||
cfdp::WidthInBytes getLenSeqNum() const override;
|
cfdp::WidthInBytes getLenSeqNum() const override;
|
||||||
cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override;
|
cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override;
|
||||||
bool hasSegmentMetadataFlag() const;
|
bool hasSegmentMetadataFlag() const override;
|
||||||
void setSegmentationControl(cfdp::SegmentationControl);
|
void setSegmentationControl(cfdp::SegmentationControl);
|
||||||
|
|
||||||
void getSourceId(cfdp::EntityId& sourceId) const override;
|
void getSourceId(cfdp::EntityId& sourceId) const override;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
||||||
class FixedArrayList : public ArrayList<T, count_t> {
|
class FixedArrayList : public ArrayList<T, count_t> {
|
||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER) && !defined(__clang__)
|
||||||
static_assert(MAX_SIZE <= (std::pow(2, sizeof(count_t) * 8) - 1),
|
static_assert(MAX_SIZE <= (std::pow(2, sizeof(count_t) * 8) - 1),
|
||||||
"count_t is not large enough to hold MAX_SIZE");
|
"count_t is not large enough to hold MAX_SIZE");
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,16 +10,23 @@ class HybridIterator : public LinkedElement<T>::Iterator, public ArrayList<T, co
|
|||||||
HybridIterator() {}
|
HybridIterator() {}
|
||||||
|
|
||||||
HybridIterator(typename LinkedElement<T>::Iterator *iter)
|
HybridIterator(typename LinkedElement<T>::Iterator *iter)
|
||||||
: LinkedElement<T>::Iterator(*iter), value(iter->value), linked(true) {}
|
: LinkedElement<T>::Iterator(*iter), linked(true) {
|
||||||
|
if (iter != nullptr) {
|
||||||
|
value = iter->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HybridIterator(LinkedElement<T> *start)
|
HybridIterator(LinkedElement<T> *start) : LinkedElement<T>::Iterator(start), linked(true) {
|
||||||
: LinkedElement<T>::Iterator(start), value(start->value), linked(true) {}
|
if (start != nullptr) {
|
||||||
|
value = start->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
||||||
typename ArrayList<T, count_t>::Iterator end)
|
typename ArrayList<T, count_t>::Iterator end)
|
||||||
: ArrayList<T, count_t>::Iterator(start), value(start.value), linked(false), end(end.value) {
|
: ArrayList<T, count_t>::Iterator(start), value(start.value), linked(false), end(end.value) {
|
||||||
if (value == this->end) {
|
if (value == this->end) {
|
||||||
value = NULL;
|
value = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ class ControllerBase : public HasModesIF,
|
|||||||
virtual void performControlOperation() = 0;
|
virtual void performControlOperation() = 0;
|
||||||
|
|
||||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t *msToReachTheMode) = 0;
|
uint32_t *msToReachTheMode) override = 0;
|
||||||
|
|
||||||
const object_id_t parentId;
|
const object_id_t parentId;
|
||||||
|
|
||||||
@ -80,9 +80,9 @@ class ControllerBase : public HasModesIF,
|
|||||||
|
|
||||||
/** Mode helpers */
|
/** Mode helpers */
|
||||||
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
||||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
virtual void startTransition(Mode_t mode, Submode_t submode) override;
|
||||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
virtual void getMode(Mode_t *mode, Submode_t *submode) override;
|
||||||
virtual void setToExternalControl();
|
virtual void setToExternalControl() override;
|
||||||
virtual void announceMode(bool recursive);
|
virtual void announceMode(bool recursive);
|
||||||
/** HK helpers */
|
/** HK helpers */
|
||||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||||
|
@ -109,7 +109,7 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t unlockDataPool() override;
|
virtual ReturnValue_t unlockDataPool() override;
|
||||||
|
|
||||||
virtual uint16_t getFillCount() const;
|
virtual uint16_t getFillCount() const override;
|
||||||
|
|
||||||
/* SerializeIF implementations */
|
/* SerializeIF implementations */
|
||||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
|
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
|
||||||
|
@ -787,9 +787,9 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i
|
|||||||
// Serialize set packet into store.
|
// Serialize set packet into store.
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG);
|
result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG);
|
||||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeId);
|
ipcStore->deleteData(storeId);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (expectedSize != size) {
|
if (expectedSize != size) {
|
||||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateSetStructurePacket",
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateSetStructurePacket",
|
||||||
@ -806,8 +806,8 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = hkQueue->reply(&reply);
|
result = hkQueue->reply(&reply);
|
||||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeId);
|
ipcStore->deleteData(storeId);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -94,13 +94,14 @@ ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(
|
|||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||||
const uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount) / 8.0);
|
const uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount) / 8.0);
|
||||||
uint8_t *validityPtr = nullptr;
|
uint8_t *validityPtr = nullptr;
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER) || defined(__clang__)
|
||||||
/* Use a std::vector here because MSVC will (rightly) not create a fixed size array
|
// Use a std::vector here because MSVC will (rightly) not create a fixed size array
|
||||||
with a non constant size specifier */
|
// with a non constant size specifier. The Apple compiler (LLVM) will not accept
|
||||||
std::vector<uint8_t> validityMask(validityMaskSize);
|
// the initialization of a variable sized array
|
||||||
|
std::vector<uint8_t> validityMask(validityMaskSize, 0);
|
||||||
validityPtr = validityMask.data();
|
validityPtr = validityMask.data();
|
||||||
#else
|
#else
|
||||||
uint8_t validityMask[validityMaskSize] = {0};
|
uint8_t validityMask[validityMaskSize] = {};
|
||||||
validityPtr = validityMask;
|
validityPtr = validityMask;
|
||||||
#endif
|
#endif
|
||||||
uint8_t validBufferIndex = 0;
|
uint8_t validBufferIndex = 0;
|
||||||
|
@ -23,8 +23,8 @@ class LocalPoolObjectBase : public PoolVariableIF, public HasReturnvaluesIF, pub
|
|||||||
LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
|
LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
|
||||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||||
|
|
||||||
void setReadWriteMode(pool_rwm_t newReadWriteMode);
|
void setReadWriteMode(pool_rwm_t newReadWriteMode) override;
|
||||||
pool_rwm_t getReadWriteMode() const;
|
pool_rwm_t getReadWriteMode() const override;
|
||||||
|
|
||||||
bool isValid() const override;
|
bool isValid() const override;
|
||||||
void setValid(bool valid) override;
|
void setValid(bool valid) override;
|
||||||
|
@ -458,16 +458,15 @@ size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
|
|||||||
DeviceCommandId_t replyId = NO_COMMAND_ID;
|
DeviceCommandId_t replyId = NO_COMMAND_ID;
|
||||||
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
|
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
|
||||||
if (command->second.useAlternativeReplyId) {
|
if (command->second.useAlternativeReplyId) {
|
||||||
replyId = command->second.alternativeReplyId;
|
replyId = command->second.alternativeReplyId;
|
||||||
}
|
} else {
|
||||||
else {
|
replyId = commandId;
|
||||||
replyId = commandId;
|
|
||||||
}
|
}
|
||||||
DeviceReplyIter iter = deviceReplyMap.find(replyId);
|
DeviceReplyIter iter = deviceReplyMap.find(replyId);
|
||||||
if (iter != deviceReplyMap.end()) {
|
if (iter != deviceReplyMap.end()) {
|
||||||
if (iter->second.delayCycles != 0) {
|
if (iter->second.delayCycles != 0) {
|
||||||
return iter->second.replyLen;
|
return iter->second.replyLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* @param counter Specifies which Action to perform
|
* @param counter Specifies which Action to perform
|
||||||
* @return RETURN_OK for successful execution
|
* @return RETURN_OK for successful execution
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t performOperation(uint8_t counter);
|
virtual ReturnValue_t performOperation(uint8_t counter) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes the device handler
|
* @brief Initializes the device handler
|
||||||
@ -173,7 +173,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* Calls fillCommandAndReplyMap().
|
* Calls fillCommandAndReplyMap().
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t initialize();
|
virtual ReturnValue_t initialize() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Intialization steps performed after all tasks have been created.
|
* @brief Intialization steps performed after all tasks have been created.
|
||||||
@ -1058,11 +1058,11 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* @param parameter1 Optional parameter 1
|
* @param parameter1 Optional parameter 1
|
||||||
* @param parameter2 Optional parameter 2
|
* @param parameter2 Optional parameter 2
|
||||||
*/
|
*/
|
||||||
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);
|
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) override;
|
||||||
/**
|
/**
|
||||||
* Same as triggerEvent, but for forwarding if object is used as proxy.
|
* Same as triggerEvent, but for forwarding if object is used as proxy.
|
||||||
*/
|
*/
|
||||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const;
|
virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if current mode is transitional mode.
|
* Checks if current mode is transitional mode.
|
||||||
|
@ -25,7 +25,7 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
|
|||||||
: BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(maxDepth) {}
|
: BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(maxDepth) {}
|
||||||
MatchTree() : BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {}
|
MatchTree() : BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {}
|
||||||
virtual ~MatchTree() {}
|
virtual ~MatchTree() {}
|
||||||
virtual bool match(T number) { return matchesTree(number); }
|
virtual bool match(T number) override { return matchesTree(number); }
|
||||||
bool matchesTree(T number) {
|
bool matchesTree(T number) {
|
||||||
iterator iter = this->begin();
|
iterator iter = this->begin();
|
||||||
if (iter == this->end()) {
|
if (iter == this->end()) {
|
||||||
@ -179,6 +179,9 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
|
|||||||
virtual ReturnValue_t cleanUpElement(iterator position) { return HasReturnvaluesIF::RETURN_OK; }
|
virtual ReturnValue_t cleanUpElement(iterator position) { return HasReturnvaluesIF::RETURN_OK; }
|
||||||
|
|
||||||
bool matchSubtree(iterator iter, T number) {
|
bool matchSubtree(iterator iter, T number) {
|
||||||
|
if (iter == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool isMatch = iter->match(number);
|
bool isMatch = iter->match(number);
|
||||||
if (isMatch) {
|
if (isMatch) {
|
||||||
if (iter.left() == this->end()) {
|
if (iter.left() == this->end()) {
|
||||||
|
@ -15,7 +15,7 @@ class RangeMatcher : public SerializeableMatcherIF<T> {
|
|||||||
RangeMatcher(T lowerBound, T upperBound, bool inverted = false)
|
RangeMatcher(T lowerBound, T upperBound, bool inverted = false)
|
||||||
: inverted(inverted), lowerBound(lowerBound), upperBound(upperBound) {}
|
: inverted(inverted), lowerBound(lowerBound), upperBound(upperBound) {}
|
||||||
|
|
||||||
bool match(T input) {
|
bool match(T input) override {
|
||||||
if (inverted) {
|
if (inverted) {
|
||||||
return !doMatch(input);
|
return !doMatch(input);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include "MessageQueueBase.h"
|
#include "MessageQueueBase.h"
|
||||||
|
|
||||||
MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest,
|
MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* args)
|
||||||
MqArgs* args): id(id) {
|
: id(id) {
|
||||||
this->defaultDest = defaultDest;
|
this->defaultDest = defaultDest;
|
||||||
if(args != nullptr) {
|
if (args != nullptr) {
|
||||||
this->args = *args;
|
this->args = *args;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -23,35 +23,25 @@ ReturnValue_t MessageQueueBase::reply(MessageQueueMessageIF* message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueueBase::receiveMessage(MessageQueueMessageIF* message,
|
ReturnValue_t MessageQueueBase::receiveMessage(MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t* receivedFrom) {
|
MessageQueueId_t* receivedFrom) {
|
||||||
ReturnValue_t status = this->receiveMessage(message);
|
ReturnValue_t status = this->receiveMessage(message);
|
||||||
*receivedFrom = this->last;
|
*receivedFrom = this->last;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueueBase::getLastPartner() const {
|
MessageQueueId_t MessageQueueBase::getLastPartner() const { return last; }
|
||||||
return last;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageQueueId_t MessageQueueBase::getId() const {
|
MessageQueueId_t MessageQueueBase::getId() const { return id; }
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
MqArgs& MessageQueueBase::getMqArgs() {
|
MqArgs& MessageQueueBase::getMqArgs() { return args; }
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageQueueBase::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
void MessageQueueBase::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
||||||
this->defaultDest = defaultDestination;
|
this->defaultDest = defaultDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueueBase::getDefaultDestination() const {
|
MessageQueueId_t MessageQueueBase::getDefaultDestination() const { return defaultDest; }
|
||||||
return defaultDest;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MessageQueueBase::isDefaultDestinationSet() const {
|
bool MessageQueueBase::isDefaultDestinationSet() const { return (defaultDest != NO_QUEUE); }
|
||||||
return (defaultDest != NO_QUEUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueueBase::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
ReturnValue_t MessageQueueBase::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
bool ignoreFault) {
|
bool ignoreFault) {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#ifndef FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
|
#ifndef FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
|
||||||
#define FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
|
#define FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
|
||||||
|
|
||||||
#include <fsfw/ipc/definitions.h>
|
|
||||||
#include <fsfw/ipc/MessageQueueIF.h>
|
#include <fsfw/ipc/MessageQueueIF.h>
|
||||||
|
#include <fsfw/ipc/definitions.h>
|
||||||
|
|
||||||
class MessageQueueBase: public MessageQueueIF {
|
class MessageQueueBase : public MessageQueueIF {
|
||||||
public:
|
public:
|
||||||
MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* mqArgs);
|
MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* mqArgs);
|
||||||
virtual ~MessageQueueBase();
|
virtual ~MessageQueueBase();
|
||||||
|
|
||||||
@ -17,25 +17,24 @@ public:
|
|||||||
virtual MessageQueueId_t getDefaultDestination() const override;
|
virtual MessageQueueId_t getDefaultDestination() const override;
|
||||||
virtual bool isDefaultDestinationSet() const override;
|
virtual bool isDefaultDestinationSet() const override;
|
||||||
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
bool ignoreFault) override;
|
bool ignoreFault) override;
|
||||||
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
|
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
|
||||||
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override;
|
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override;
|
||||||
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t* receivedFrom) override;
|
MessageQueueId_t* receivedFrom) override;
|
||||||
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
|
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault = false) override;
|
bool ignoreFault = false) override;
|
||||||
|
|
||||||
// OSAL specific, forward the abstract function
|
// OSAL specific, forward the abstract function
|
||||||
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
|
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
|
||||||
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault = false) = 0;
|
MessageQueueId_t sentFrom, bool ignoreFault = false) = 0;
|
||||||
protected:
|
|
||||||
|
protected:
|
||||||
MessageQueueId_t id = MessageQueueIF::NO_QUEUE;
|
MessageQueueId_t id = MessageQueueIF::NO_QUEUE;
|
||||||
MessageQueueId_t last = MessageQueueIF::NO_QUEUE;
|
MessageQueueId_t last = MessageQueueIF::NO_QUEUE;
|
||||||
MessageQueueId_t defaultDest = MessageQueueIF::NO_QUEUE;
|
MessageQueueId_t defaultDest = MessageQueueIF::NO_QUEUE;
|
||||||
MqArgs args = {};
|
MqArgs args = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ */
|
#endif /* FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ */
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define FSFW_IPC_MESSAGEQUEUEIF_H_
|
#define FSFW_IPC_MESSAGEQUEUEIF_H_
|
||||||
|
|
||||||
#include <fsfw/ipc/definitions.h>
|
#include <fsfw/ipc/definitions.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
@ -45,7 +46,8 @@ class MessageQueueIF {
|
|||||||
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
|
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function reads available messages from the message queue and returns the sender.
|
* @brief This function reads available messages from the message queue and returns the
|
||||||
|
* sender.
|
||||||
* @details
|
* @details
|
||||||
* It works identically to the other receiveMessage call, but in addition
|
* It works identically to the other receiveMessage call, but in addition
|
||||||
* returns the sender's queue id.
|
* returns the sender's queue id.
|
||||||
|
@ -34,7 +34,7 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
|
|||||||
SerializeElement<T> limitValue;
|
SerializeElement<T> limitValue;
|
||||||
SerializeElement<ReturnValue_t> oldState;
|
SerializeElement<ReturnValue_t> oldState;
|
||||||
SerializeElement<ReturnValue_t> newState;
|
SerializeElement<ReturnValue_t> newState;
|
||||||
uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE];
|
uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE] = {};
|
||||||
SerializeElement<SerialBufferAdapter<uint8_t>> timestampSerializer;
|
SerializeElement<SerialBufferAdapter<uint8_t>> timestampSerializer;
|
||||||
TimeStamperIF* timeStamper;
|
TimeStamperIF* timeStamper;
|
||||||
MonitoringReportContent()
|
MonitoringReportContent()
|
||||||
@ -46,7 +46,6 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
|
|||||||
limitValue(0),
|
limitValue(0),
|
||||||
oldState(0),
|
oldState(0),
|
||||||
newState(0),
|
newState(0),
|
||||||
rawTimestamp({0}),
|
|
||||||
timestampSerializer(rawTimestamp, sizeof(rawTimestamp)),
|
timestampSerializer(rawTimestamp, sizeof(rawTimestamp)),
|
||||||
timeStamper(NULL) {
|
timeStamper(NULL) {
|
||||||
setAllNext();
|
setAllNext();
|
||||||
|
@ -48,9 +48,9 @@ class SystemObject : public SystemObjectIF {
|
|||||||
virtual ~SystemObject();
|
virtual ~SystemObject();
|
||||||
object_id_t getObjectId() const override;
|
object_id_t getObjectId() const override;
|
||||||
virtual ReturnValue_t initialize() override;
|
virtual ReturnValue_t initialize() override;
|
||||||
virtual ReturnValue_t checkObjectConnections();
|
virtual ReturnValue_t checkObjectConnections() override;
|
||||||
|
|
||||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const;
|
virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */
|
#endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */
|
||||||
|
@ -16,11 +16,13 @@
|
|||||||
//! Debugging preprocessor define.
|
//! Debugging preprocessor define.
|
||||||
#define FSFW_UDP_RECV_WIRETAPPING_ENABLED 0
|
#define FSFW_UDP_RECV_WIRETAPPING_ENABLED 0
|
||||||
|
|
||||||
|
const timeval UdpTcPollingTask::DEFAULT_TIMEOUT = {0, 500000};
|
||||||
|
|
||||||
UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge,
|
UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge,
|
||||||
size_t maxRecvSize, double timeoutSeconds)
|
size_t maxRecvSize, double timeoutSeconds)
|
||||||
: SystemObject(objectId), tmtcBridgeId(tmtcUdpBridge) {
|
: SystemObject(objectId), tmtcBridgeId(tmtcUdpBridge) {
|
||||||
if (frameSize > 0) {
|
if (maxRecvSize > 0) {
|
||||||
this->frameSize = frameSize;
|
this->frameSize = maxRecvSize;
|
||||||
} else {
|
} else {
|
||||||
this->frameSize = DEFAULT_MAX_RECV_SIZE;
|
this->frameSize = DEFAULT_MAX_RECV_SIZE;
|
||||||
}
|
}
|
||||||
@ -31,22 +33,20 @@ UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBrid
|
|||||||
receptionBuffer.resize(this->frameSize);
|
receptionBuffer.resize(this->frameSize);
|
||||||
|
|
||||||
if (timeoutSeconds == -1) {
|
if (timeoutSeconds == -1) {
|
||||||
receptionTimeout = DEFAULT_TIMEOUT;
|
receptionTimeout = UdpTcPollingTask::DEFAULT_TIMEOUT;
|
||||||
} else {
|
} else {
|
||||||
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
|
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UdpTcPollingTask::~UdpTcPollingTask() {}
|
[[noreturn]] ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
|
||||||
|
|
||||||
ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
|
|
||||||
/* Sender Address is cached here. */
|
/* Sender Address is cached here. */
|
||||||
struct sockaddr senderAddress;
|
struct sockaddr senderAddress {};
|
||||||
socklen_t senderAddressSize = sizeof(senderAddress);
|
socklen_t senderAddressSize = sizeof(senderAddress);
|
||||||
|
|
||||||
/* Poll for new UDP datagrams in permanent loop. */
|
/* Poll for new UDP datagrams in permanent loop. */
|
||||||
while (true) {
|
while (true) {
|
||||||
int bytesReceived =
|
ssize_t bytesReceived =
|
||||||
recvfrom(this->serverSocket, reinterpret_cast<char*>(receptionBuffer.data()), frameSize,
|
recvfrom(this->serverSocket, reinterpret_cast<char*>(receptionBuffer.data()), frameSize,
|
||||||
receptionFlags, &senderAddress, &senderAddressSize);
|
receptionFlags, &senderAddress, &senderAddressSize);
|
||||||
if (bytesReceived == SOCKET_ERROR) {
|
if (bytesReceived == SOCKET_ERROR) {
|
||||||
@ -70,7 +70,6 @@ ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
|
|||||||
}
|
}
|
||||||
tmtcBridge->checkAndSetClientAddress(senderAddress);
|
tmtcBridge->checkAndSetClientAddress(senderAddress);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
|
ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
|
||||||
@ -155,7 +154,7 @@ void UdpTcPollingTask::setTimeout(double timeoutSeconds) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#elif defined(PLATFORM_UNIX)
|
#elif defined(PLATFORM_UNIX)
|
||||||
timeval tval;
|
timeval tval {};
|
||||||
tval = timevalOperations::toTimeval(timeoutSeconds);
|
tval = timevalOperations::toTimeval(timeoutSeconds);
|
||||||
int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(receptionTimeout));
|
int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(receptionTimeout));
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
|
@ -21,11 +21,11 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl
|
|||||||
public:
|
public:
|
||||||
static constexpr size_t DEFAULT_MAX_RECV_SIZE = 1500;
|
static constexpr size_t DEFAULT_MAX_RECV_SIZE = 1500;
|
||||||
//! 0.5 default milliseconds timeout for now.
|
//! 0.5 default milliseconds timeout for now.
|
||||||
static constexpr timeval DEFAULT_TIMEOUT = {0, 500};
|
static const timeval DEFAULT_TIMEOUT;
|
||||||
|
|
||||||
UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge, size_t maxRecvSize = 0,
|
UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge, size_t maxRecvSize = 0,
|
||||||
double timeoutSeconds = -1);
|
double timeoutSeconds = -1);
|
||||||
virtual ~UdpTcPollingTask();
|
~UdpTcPollingTask() override = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn on optional timeout for UDP polling. In the default mode,
|
* Turn on optional timeout for UDP polling. In the default mode,
|
||||||
@ -34,9 +34,9 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl
|
|||||||
*/
|
*/
|
||||||
void setTimeout(double timeoutSeconds);
|
void setTimeout(double timeoutSeconds);
|
||||||
|
|
||||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
[[noreturn]] ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
virtual ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StorageManagerIF* tcStore = nullptr;
|
StorageManagerIF* tcStore = nullptr;
|
||||||
@ -51,7 +51,7 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl
|
|||||||
std::vector<uint8_t> receptionBuffer;
|
std::vector<uint8_t> receptionBuffer;
|
||||||
|
|
||||||
size_t frameSize = 0;
|
size_t frameSize = 0;
|
||||||
timeval receptionTimeout;
|
timeval receptionTimeout{};
|
||||||
|
|
||||||
ReturnValue_t handleSuccessfullTcRead(size_t bytesRead);
|
ReturnValue_t handleSuccessfullTcRead(size_t bytesRead);
|
||||||
};
|
};
|
||||||
|
@ -20,13 +20,13 @@
|
|||||||
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
||||||
|
|
||||||
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
std::string udpServerPort, object_id_t tmStoreId,
|
const std::string& udpServerPort_, object_id_t tmStoreId,
|
||||||
object_id_t tcStoreId)
|
object_id_t tcStoreId)
|
||||||
: TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
|
: TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
|
||||||
if (udpServerPort == "") {
|
if (udpServerPort_.empty()) {
|
||||||
this->udpServerPort = DEFAULT_SERVER_PORT;
|
udpServerPort = DEFAULT_SERVER_PORT;
|
||||||
} else {
|
} else {
|
||||||
this->udpServerPort = udpServerPort;
|
udpServerPort = udpServerPort_;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
@ -117,7 +117,7 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
|||||||
tcpip::printAddress(&clientAddress);
|
tcpip::printAddress(&clientAddress);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int bytesSent = sendto(serverSocket, reinterpret_cast<const char *>(data), dataLen, flags,
|
ssize_t bytesSent = sendto(serverSocket, reinterpret_cast<const char *>(data), dataLen, flags,
|
||||||
&clientAddress, clientAddressLen);
|
&clientAddress, clientAddressLen);
|
||||||
if (bytesSent == SOCKET_ERROR) {
|
if (bytesSent == SOCKET_ERROR) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
@ -150,7 +150,7 @@ void UdpTmTcBridge::checkAndSetClientAddress(sockaddr &newAddress) {
|
|||||||
clientAddressLen = sizeof(clientAddress);
|
clientAddressLen = sizeof(clientAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UdpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs) {
|
void UdpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType_, dur_millis_t timeoutMs) {
|
||||||
this->timeoutType = timeoutType;
|
timeoutType = timeoutType_;
|
||||||
this->mutexTimeoutMs = timeoutMs;
|
mutexTimeoutMs = timeoutMs;
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,10 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase {
|
|||||||
/* The ports chosen here should not be used by any other process. */
|
/* The ports chosen here should not be used by any other process. */
|
||||||
static const std::string DEFAULT_SERVER_PORT;
|
static const std::string DEFAULT_SERVER_PORT;
|
||||||
|
|
||||||
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, std::string udpServerPort = "",
|
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, const std::string& udpServerPort = "",
|
||||||
object_id_t tmStoreId = objects::TM_STORE,
|
object_id_t tmStoreId = objects::TM_STORE,
|
||||||
object_id_t tcStoreId = objects::TC_STORE);
|
object_id_t tcStoreId = objects::TC_STORE);
|
||||||
virtual ~UdpTmTcBridge();
|
~UdpTmTcBridge() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set properties of internal mutex.
|
* Set properties of internal mutex.
|
||||||
@ -46,12 +46,12 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase {
|
|||||||
std::string getUdpPort() const;
|
std::string getUdpPort() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ReturnValue_t sendTm(const uint8_t* data, size_t dataLen) override;
|
ReturnValue_t sendTm(const uint8_t* data, size_t dataLen) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string udpServerPort;
|
std::string udpServerPort;
|
||||||
|
|
||||||
struct sockaddr clientAddress;
|
struct sockaddr clientAddress = {};
|
||||||
socklen_t clientAddressLen = 0;
|
socklen_t clientAddressLen = 0;
|
||||||
|
|
||||||
//! Access to the client address is mutex protected as it is set by another task.
|
//! Access to the client address is mutex protected as it is set by another task.
|
||||||
|
@ -11,9 +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
|
||||||
|
|
||||||
uint16_t Clock::leapSeconds = 0;
|
|
||||||
MutexIF* Clock::timeMutex = nullptr;
|
|
||||||
|
|
||||||
uint32_t Clock::getTicksPerSecond(void) { return 1000; }
|
uint32_t Clock::getTicksPerSecond(void) { return 1000; }
|
||||||
|
|
||||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
||||||
|
|
||||||
#include <fsfw/ipc/MessageQueueBase.h>
|
#include <fsfw/ipc/MessageQueueBase.h>
|
||||||
|
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "TaskManagement.h"
|
#include "TaskManagement.h"
|
||||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||||
|
@ -1,24 +1,27 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
PRIVATE
|
Clock.cpp
|
||||||
Clock.cpp
|
FixedTimeslotTask.cpp
|
||||||
FixedTimeslotTask.cpp
|
MessageQueue.cpp
|
||||||
MessageQueue.cpp
|
Mutex.cpp
|
||||||
Mutex.cpp
|
MutexFactory.cpp
|
||||||
MutexFactory.cpp
|
PeriodicTask.cpp
|
||||||
PeriodicTask.cpp
|
QueueFactory.cpp
|
||||||
QueueFactory.cpp
|
QueueMapManager.cpp
|
||||||
QueueMapManager.cpp
|
SemaphoreFactory.cpp
|
||||||
SemaphoreFactory.cpp
|
TaskFactory.cpp
|
||||||
TaskFactory.cpp
|
taskHelpers.cpp
|
||||||
taskHelpers.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME}
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||||
PRIVATE
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
rt
|
)
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
if(NOT APPLE)
|
||||||
)
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||||
|
rt
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "fsfw/ipc/MutexGuard.h"
|
||||||
#include "fsfw/platform.h"
|
#include "fsfw/platform.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
@ -11,9 +12,6 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint16_t Clock::leapSeconds = 0;
|
|
||||||
MutexIF* Clock::timeMutex = NULL;
|
|
||||||
|
|
||||||
using SystemClock = std::chrono::system_clock;
|
using SystemClock = std::chrono::system_clock;
|
||||||
|
|
||||||
uint32_t Clock::getTicksPerSecond(void) {
|
uint32_t Clock::getTicksPerSecond(void) {
|
||||||
@ -127,6 +125,13 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
|||||||
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
||||||
auto fraction = now - seconds;
|
auto fraction = now - seconds;
|
||||||
time_t tt = SystemClock::to_time_t(now);
|
time_t tt = SystemClock::to_time_t(now);
|
||||||
|
ReturnValue_t result = checkOrCreateClockMutex();
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
MutexGuard helper(timeMutex);
|
||||||
|
// gmtime writes its output in a global buffer which is not Thread Safe
|
||||||
|
// Therefore we have to use a Mutex here
|
||||||
struct tm* timeInfo;
|
struct tm* timeInfo;
|
||||||
timeInfo = gmtime(&tt);
|
timeInfo = gmtime(&tt);
|
||||||
time->year = timeInfo->tm_year + 1900;
|
time->year = timeInfo->tm_year + 1900;
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
|
#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
|
||||||
#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
|
#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
|
||||||
|
|
||||||
#include "fsfw/ipc/MessageQueueBase.h"
|
#include <memory>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||||
|
#include "fsfw/ipc/MessageQueueBase.h"
|
||||||
#include "fsfw/ipc/MessageQueueIF.h"
|
#include "fsfw/ipc/MessageQueueIF.h"
|
||||||
#include "fsfw/ipc/MessageQueueMessage.h"
|
#include "fsfw/ipc/MessageQueueMessage.h"
|
||||||
#include "fsfw/ipc/MutexIF.h"
|
#include "fsfw/ipc/MutexIF.h"
|
||||||
#include "fsfw/ipc/definitions.h"
|
#include "fsfw/ipc/definitions.h"
|
||||||
#include "fsfw/timemanager/Clock.h"
|
#include "fsfw/timemanager/Clock.h"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class manages sending and receiving of
|
* @brief This class manages sending and receiving of
|
||||||
* message queue messages.
|
* message queue messages.
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
Clock.cpp
|
Clock.cpp
|
||||||
BinarySemaphore.cpp
|
BinarySemaphore.cpp
|
||||||
CountingSemaphore.cpp
|
CountingSemaphore.cpp
|
||||||
FixedTimeslotTask.cpp
|
FixedTimeslotTask.cpp
|
||||||
InternalErrorCodes.cpp
|
InternalErrorCodes.cpp
|
||||||
MessageQueue.cpp
|
MessageQueue.cpp
|
||||||
Mutex.cpp
|
Mutex.cpp
|
||||||
MutexFactory.cpp
|
MutexFactory.cpp
|
||||||
PeriodicPosixTask.cpp
|
PeriodicPosixTask.cpp
|
||||||
PosixThread.cpp
|
PosixThread.cpp
|
||||||
QueueFactory.cpp
|
QueueFactory.cpp
|
||||||
SemaphoreFactory.cpp
|
SemaphoreFactory.cpp
|
||||||
TaskFactory.cpp
|
TaskFactory.cpp
|
||||||
tcpipHelpers.cpp
|
tcpipHelpers.cpp
|
||||||
unixUtility.cpp
|
unixUtility.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PUBLIC
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT APPLE)
|
||||||
|
target_link_libraries(${LIB_FSFW_NAME} PUBLIC
|
||||||
rt
|
rt
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
target_link_libraries(${LIB_FSFW_NAME} INTERFACE
|
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
@ -8,11 +8,9 @@
|
|||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "fsfw/ipc/MutexGuard.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
uint16_t Clock::leapSeconds = 0;
|
|
||||||
MutexIF* Clock::timeMutex = NULL;
|
|
||||||
|
|
||||||
uint32_t Clock::getTicksPerSecond(void) {
|
uint32_t Clock::getTicksPerSecond(void) {
|
||||||
uint32_t ticks = sysconf(_SC_CLK_TCK);
|
uint32_t ticks = sysconf(_SC_CLK_TCK);
|
||||||
return ticks;
|
return ticks;
|
||||||
@ -117,7 +115,13 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
|||||||
// TODO errno
|
// TODO errno
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
ReturnValue_t result = checkOrCreateClockMutex();
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
MutexGuard helper(timeMutex);
|
||||||
|
// gmtime writes its output in a global buffer which is not Thread Safe
|
||||||
|
// Therefore we have to use a Mutex here
|
||||||
struct tm* timeInfo;
|
struct tm* timeInfo;
|
||||||
timeInfo = gmtime(&timeUnix.tv_sec);
|
timeInfo = gmtime(&timeUnix.tv_sec);
|
||||||
time->year = timeInfo->tm_year + 1900;
|
time->year = timeInfo->tm_year + 1900;
|
||||||
|
@ -61,8 +61,7 @@ class MessageQueue : public MessageQueueBase {
|
|||||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
||||||
ReturnValue_t flush(uint32_t* count) override;
|
ReturnValue_t flush(uint32_t* count) override;
|
||||||
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom,
|
MessageQueueId_t sentFrom, bool ignoreFault = false) override;
|
||||||
bool ignoreFault = false) override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
|
@ -6,9 +6,6 @@
|
|||||||
#include "fsfw/ipc/MutexGuard.h"
|
#include "fsfw/ipc/MutexGuard.h"
|
||||||
#include "fsfw/osal/rtems/RtemsBasic.h"
|
#include "fsfw/osal/rtems/RtemsBasic.h"
|
||||||
|
|
||||||
uint16_t Clock::leapSeconds = 0;
|
|
||||||
MutexIF* Clock::timeMutex = nullptr;
|
|
||||||
|
|
||||||
uint32_t Clock::getTicksPerSecond(void) {
|
uint32_t Clock::getTicksPerSecond(void) {
|
||||||
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
|
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
|
||||||
return static_cast<uint32_t>(ticks_per_second);
|
return static_cast<uint32_t>(ticks_per_second);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
|
#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
|
||||||
|
|
||||||
#include <fsfw/ipc/MessageQueueBase.h>
|
#include <fsfw/ipc/MessageQueueBase.h>
|
||||||
|
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||||
#include "fsfw/ipc/MessageQueueIF.h"
|
#include "fsfw/ipc/MessageQueueIF.h"
|
||||||
@ -52,8 +53,8 @@ class MessageQueue : public MessageQueueBase {
|
|||||||
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||||
ReturnValue_t flush(uint32_t* count) override;
|
ReturnValue_t flush(uint32_t* count) override;
|
||||||
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||||
bool ignoreFault = false) override;
|
bool ignoreFault = false) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
@ -59,14 +59,13 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t addComponent(object_id_t object) override;
|
ReturnValue_t addComponent(object_id_t object) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an object to the list of objects to be executed.
|
* Adds an object to the list of objects to be executed.
|
||||||
* The objects are executed in the order added.
|
* The objects are executed in the order added.
|
||||||
* @param object pointer to the object to add.
|
* @param object pointer to the object to add.
|
||||||
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
|
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
|
ReturnValue_t addComponent(ExecutableObjectIF *object) override;
|
||||||
|
|
||||||
|
|
||||||
uint32_t getPeriodMs() const override;
|
uint32_t getPeriodMs() const override;
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class Fuse : public SystemObject,
|
|||||||
|
|
||||||
ReturnValue_t check();
|
ReturnValue_t check();
|
||||||
uint8_t getFuseId() const;
|
uint8_t getFuseId() const;
|
||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize() override;
|
||||||
DeviceList devices;
|
DeviceList devices;
|
||||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
SerializeIF::Endianness streamEndianness) const override;
|
SerializeIF::Endianness streamEndianness) const override;
|
||||||
|
@ -43,7 +43,7 @@ class Service3Housekeeping : public CommandingServiceBase, public AcceptsHkPacke
|
|||||||
CommandMessage* optionalNextCommand, object_id_t objectId,
|
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||||
bool* isStep) override;
|
bool* isStep) override;
|
||||||
|
|
||||||
virtual MessageQueueId_t getHkQueue() const;
|
virtual MessageQueueId_t getHkQueue() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Subservice {
|
enum class Subservice {
|
||||||
|
@ -30,11 +30,11 @@ ReturnValue_t Subsystem::checkSequence(HybridIterator<ModeListEntry> iter,
|
|||||||
return FALLBACK_SEQUENCE_DOES_NOT_EXIST;
|
return FALLBACK_SEQUENCE_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter.value == NULL) {
|
if (iter.value == nullptr) {
|
||||||
return NO_TARGET_TABLE;
|
return NO_TARGET_TABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; iter.value != NULL; ++iter) {
|
for (; iter.value != nullptr; ++iter) {
|
||||||
if (!existsModeTable(iter->getTableId())) {
|
if (!existsModeTable(iter->getTableId())) {
|
||||||
return TABLE_DOES_NOT_EXIST;
|
return TABLE_DOES_NOT_EXIST;
|
||||||
} else {
|
} else {
|
||||||
@ -66,13 +66,18 @@ HybridIterator<ModeListEntry> Subsystem::getCurrentTable() {
|
|||||||
void Subsystem::performChildOperation() {
|
void Subsystem::performChildOperation() {
|
||||||
if (isInTransition) {
|
if (isInTransition) {
|
||||||
if (commandsOutstanding <= 0) { // all children of the current table were commanded and replied
|
if (commandsOutstanding <= 0) { // all children of the current table were commanded and replied
|
||||||
if (currentSequenceIterator.value == NULL) { // we're through with this sequence
|
if (currentSequenceIterator.value == nullptr) { // we're through with this sequence
|
||||||
if (checkStateAgainstTable(currentTargetTable, targetSubmode) == RETURN_OK) {
|
if (checkStateAgainstTable(currentTargetTable, targetSubmode) == RETURN_OK) {
|
||||||
setMode(targetMode, targetSubmode);
|
setMode(targetMode, targetSubmode);
|
||||||
isInTransition = false;
|
isInTransition = false;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
transitionFailed(TARGET_TABLE_NOT_REACHED, getSequence(targetMode)->getTableId());
|
Mode_t tableId = 0;
|
||||||
|
auto seq = getSequence(targetMode);
|
||||||
|
if (seq.value != nullptr) {
|
||||||
|
tableId = seq->getTableId();
|
||||||
|
}
|
||||||
|
transitionFailed(TARGET_TABLE_NOT_REACHED, tableId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,10 +253,13 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) {
|
|||||||
case ModeSequenceMessage::READ_TABLE: {
|
case ModeSequenceMessage::READ_TABLE: {
|
||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
Mode_t table = ModeSequenceMessage::getSequenceId(message);
|
Mode_t table = ModeSequenceMessage::getSequenceId(message);
|
||||||
EntryPointer *entry = NULL;
|
EntryPointer *entry = nullptr;
|
||||||
result = modeTables.find(table, &entry);
|
result = modeTables.find(table, &entry);
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK or entry == nullptr) {
|
||||||
replyToCommand(result, 0);
|
replyToCommand(result, 0);
|
||||||
|
if (entry == nullptr) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SerializeIF *elements[2];
|
SerializeIF *elements[2];
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
#ifndef FSFW_SUBSYSTEM_SUBSYSTEM_H_
|
#ifndef FSFW_SUBSYSTEM_SUBSYSTEM_H_
|
||||||
#define FSFW_SUBSYSTEM_SUBSYSTEM_H_
|
#define FSFW_SUBSYSTEM_SUBSYSTEM_H_
|
||||||
|
|
||||||
#include <FSFWConfig.h>
|
|
||||||
|
|
||||||
#include "../container/FixedArrayList.h"
|
#include "../container/FixedArrayList.h"
|
||||||
#include "../container/FixedMap.h"
|
#include "../container/FixedMap.h"
|
||||||
#include "../container/HybridIterator.h"
|
#include "../container/HybridIterator.h"
|
||||||
#include "../container/SinglyLinkedList.h"
|
#include "../container/SinglyLinkedList.h"
|
||||||
#include "../serialize/SerialArrayListAdapter.h"
|
#include "../serialize/SerialArrayListAdapter.h"
|
||||||
#include "SubsystemBase.h"
|
#include "SubsystemBase.h"
|
||||||
|
#include "fsfw/FSFW.h"
|
||||||
#include "modes/ModeDefinitions.h"
|
#include "modes/ModeDefinitions.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -127,18 +126,18 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF {
|
|||||||
|
|
||||||
ReturnValue_t deleteTable(Mode_t id);
|
ReturnValue_t deleteTable(Mode_t id);
|
||||||
|
|
||||||
virtual void performChildOperation();
|
virtual void performChildOperation() override;
|
||||||
|
|
||||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message);
|
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) override;
|
||||||
|
|
||||||
bool isFallbackSequence(Mode_t SequenceId);
|
bool isFallbackSequence(Mode_t SequenceId);
|
||||||
|
|
||||||
bool isTableUsed(Mode_t tableId);
|
bool isTableUsed(Mode_t tableId);
|
||||||
|
|
||||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t *msToReachTheMode);
|
uint32_t *msToReachTheMode) override;
|
||||||
|
|
||||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
virtual void startTransition(Mode_t mode, Submode_t submode) override;
|
||||||
|
|
||||||
void sendSerializablesAsCommandMessage(Command_t command, SerializeIF **elements, uint8_t count);
|
void sendSerializablesAsCommandMessage(Command_t command, SerializeIF **elements, uint8_t count);
|
||||||
|
|
||||||
|
@ -123,15 +123,15 @@ class SubsystemBase : public SystemObject,
|
|||||||
virtual void performChildOperation() = 0;
|
virtual void performChildOperation() = 0;
|
||||||
|
|
||||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t *msToReachTheMode) = 0;
|
uint32_t *msToReachTheMode) override = 0;
|
||||||
|
|
||||||
virtual void startTransition(Mode_t mode, Submode_t submode) = 0;
|
virtual void startTransition(Mode_t mode, Submode_t submode) override = 0;
|
||||||
|
|
||||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
virtual void getMode(Mode_t *mode, Submode_t *submode) override;
|
||||||
|
|
||||||
virtual void setToExternalControl();
|
virtual void setToExternalControl() override;
|
||||||
|
|
||||||
virtual void announceMode(bool recursive);
|
virtual void announceMode(bool recursive) override;
|
||||||
|
|
||||||
virtual void modeChanged();
|
virtual void modeChanged();
|
||||||
};
|
};
|
||||||
|
@ -6,10 +6,6 @@
|
|||||||
|
|
||||||
#include "fsfw/FSFW.h"
|
#include "fsfw/FSFW.h"
|
||||||
|
|
||||||
CCSDSTime::CCSDSTime() {}
|
|
||||||
|
|
||||||
CCSDSTime::~CCSDSTime() {}
|
|
||||||
|
|
||||||
ReturnValue_t CCSDSTime::convertToCcsds(Ccs_seconds* to, const Clock::TimeOfDay_t* from) {
|
ReturnValue_t CCSDSTime::convertToCcsds(Ccs_seconds* to, const Clock::TimeOfDay_t* from) {
|
||||||
ReturnValue_t result = checkTimeOfDay(from);
|
ReturnValue_t result = checkTimeOfDay(from);
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
@ -91,7 +87,7 @@ ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const uint8_t* f
|
|||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return convertTimevalToTimeOfDay(to, &time);
|
return Clock::convertTimevalToTimeOfDay(&time, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* from,
|
ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* from,
|
||||||
@ -428,7 +424,7 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, const uint8_t* from, size_t
|
|||||||
from++;
|
from++;
|
||||||
ReturnValue_t result = convertFromCUC(to, pField, from, foundLength, maxLength - 1);
|
ReturnValue_t result = convertFromCUC(to, pField, from, foundLength, maxLength - 1);
|
||||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||||
if (foundLength != NULL) {
|
if (foundLength != nullptr) {
|
||||||
*foundLength += 1;
|
*foundLength += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,11 +485,6 @@ ReturnValue_t CCSDSTime::checkTimeOfDay(const Clock::TimeOfDay_t* time) {
|
|||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CCSDSTime::convertTimevalToTimeOfDay(Clock::TimeOfDay_t* to, timeval* from) {
|
|
||||||
// This is rather tricky. Implement only if needed. Also, if so, move to OSAL.
|
|
||||||
return UNSUPPORTED_TIME_FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, size_t* foundLength,
|
ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, size_t* foundLength,
|
||||||
size_t maxLength) {
|
size_t maxLength) {
|
||||||
uint8_t pField = *from;
|
uint8_t pField = *from;
|
||||||
@ -583,7 +574,7 @@ ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const CCSDSTime:
|
|||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return CCSDSTime::convertTimevalToTimeOfDay(to, &tempTimeval);
|
return Clock::convertTimevalToTimeOfDay(&tempTimeval, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, const uint8_t* from,
|
ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, const uint8_t* from,
|
||||||
@ -593,18 +584,18 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, const uint8
|
|||||||
uint8_t nCoarse = ((pField & 0b1100) >> 2) + 1;
|
uint8_t nCoarse = ((pField & 0b1100) >> 2) + 1;
|
||||||
uint8_t nFine = (pField & 0b11);
|
uint8_t nFine = (pField & 0b11);
|
||||||
size_t totalLength = nCoarse + nFine;
|
size_t totalLength = nCoarse + nFine;
|
||||||
if (foundLength != NULL) {
|
if (foundLength != nullptr) {
|
||||||
*foundLength = totalLength;
|
*foundLength = totalLength;
|
||||||
}
|
}
|
||||||
if (totalLength > maxLength) {
|
if (totalLength > maxLength) {
|
||||||
return LENGTH_MISMATCH;
|
return LENGTH_MISMATCH;
|
||||||
}
|
}
|
||||||
for (int count = 0; count < nCoarse; count++) {
|
for (int count = nCoarse; count > 0; count--) {
|
||||||
secs += *from << ((nCoarse * 8 - 8) * (1 + count));
|
secs += *from << (count * 8 - 8);
|
||||||
from++;
|
from++;
|
||||||
}
|
}
|
||||||
for (int count = 0; count < nFine; count++) {
|
for (int count = nFine; count > 0; count--) {
|
||||||
subSeconds += *from << ((nFine * 8 - 8) * (1 + count));
|
subSeconds += *from << (count * 8 - 8);
|
||||||
from++;
|
from++;
|
||||||
}
|
}
|
||||||
// Move to POSIX epoch.
|
// Move to POSIX epoch.
|
||||||
|
@ -161,18 +161,37 @@ class CCSDSTime : public HasReturnvaluesIF {
|
|||||||
*/
|
*/
|
||||||
static ReturnValue_t convertFromCcsds(timeval *to, uint8_t const *from, size_t *foundLength,
|
static ReturnValue_t convertFromCcsds(timeval *to, uint8_t const *from, size_t *foundLength,
|
||||||
size_t maxLength);
|
size_t maxLength);
|
||||||
|
/**
|
||||||
|
* @brief Currently unsupported conversion due to leapseconds
|
||||||
|
*
|
||||||
|
* @param to Time Of Day (UTC)
|
||||||
|
* @param from Buffer to take the CUC from
|
||||||
|
* @param length Length of buffer
|
||||||
|
* @return ReturnValue_t UNSUPPORTED_TIME_FORMAT in any case ATM
|
||||||
|
*/
|
||||||
static ReturnValue_t convertFromCUC(Clock::TimeOfDay_t *to, uint8_t const *from, uint8_t length);
|
static ReturnValue_t convertFromCUC(Clock::TimeOfDay_t *to, uint8_t const *from, uint8_t length);
|
||||||
|
/**
|
||||||
|
* @brief Converts from CCSDS CUC to timeval
|
||||||
|
*
|
||||||
|
* If input is CCSDS Epoch this is TAI! -> No leapsecond support.
|
||||||
|
*
|
||||||
|
* Currently, it only supports seconds + 2 Byte Subseconds (1/65536 seconds)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param to Timeval to write the result to
|
||||||
|
* @param from Buffer to read from
|
||||||
|
* @param foundLength Length found by this function (can be nullptr if unused)
|
||||||
|
* @param maxLength Max length of the buffer to be read
|
||||||
|
* @return ReturnValue_t - RETURN_OK if successful
|
||||||
|
* - LENGTH_MISMATCH if expected length is larger than maxLength
|
||||||
|
*/
|
||||||
static ReturnValue_t convertFromCUC(timeval *to, uint8_t const *from, size_t *foundLength,
|
static ReturnValue_t convertFromCUC(timeval *to, uint8_t const *from, size_t *foundLength,
|
||||||
size_t maxLength);
|
size_t maxLength);
|
||||||
|
|
||||||
static ReturnValue_t convertFromCUC(timeval *to, uint8_t pField, uint8_t const *from,
|
static ReturnValue_t convertFromCUC(timeval *to, uint8_t pField, uint8_t const *from,
|
||||||
size_t *foundLength, size_t maxLength);
|
size_t *foundLength, size_t maxLength);
|
||||||
|
|
||||||
static ReturnValue_t convertFromCCS(timeval *to, uint8_t const *from, size_t *foundLength,
|
static ReturnValue_t convertFromCCS(timeval *to, uint8_t const *from, size_t *foundLength,
|
||||||
size_t maxLength);
|
size_t maxLength);
|
||||||
|
|
||||||
static ReturnValue_t convertFromCCS(timeval *to, uint8_t pField, uint8_t const *from,
|
static ReturnValue_t convertFromCCS(timeval *to, uint8_t pField, uint8_t const *from,
|
||||||
size_t *foundLength, size_t maxLength);
|
size_t *foundLength, size_t maxLength);
|
||||||
|
|
||||||
@ -192,8 +211,8 @@ class CCSDSTime : public HasReturnvaluesIF {
|
|||||||
static uint32_t subsecondsToMicroseconds(uint16_t subseconds);
|
static uint32_t subsecondsToMicroseconds(uint16_t subseconds);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CCSDSTime();
|
CCSDSTime(){};
|
||||||
virtual ~CCSDSTime();
|
virtual ~CCSDSTime(){};
|
||||||
/**
|
/**
|
||||||
* checks a ccs time stream for validity
|
* checks a ccs time stream for validity
|
||||||
*
|
*
|
||||||
@ -223,7 +242,6 @@ class CCSDSTime : public HasReturnvaluesIF {
|
|||||||
uint8_t *day);
|
uint8_t *day);
|
||||||
|
|
||||||
static bool isLeapYear(uint32_t year);
|
static bool isLeapYear(uint32_t year);
|
||||||
static ReturnValue_t convertTimevalToTimeOfDay(Clock::TimeOfDay_t *to, timeval *from);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_TIMEMANAGER_CCSDSTIME_H_ */
|
#endif /* FSFW_TIMEMANAGER_CCSDSTIME_H_ */
|
||||||
|
@ -99,6 +99,13 @@ class Clock {
|
|||||||
*/
|
*/
|
||||||
static ReturnValue_t getDateAndTime(TimeOfDay_t *time);
|
static ReturnValue_t getDateAndTime(TimeOfDay_t *time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert to time of day struct given the POSIX timeval struct
|
||||||
|
* @param from
|
||||||
|
* @param to
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
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
|
||||||
@ -166,6 +173,7 @@ class Clock {
|
|||||||
|
|
||||||
static MutexIF *timeMutex;
|
static MutexIF *timeMutex;
|
||||||
static uint16_t leapSeconds;
|
static uint16_t leapSeconds;
|
||||||
|
static bool leapSecondsSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_TIMEMANAGER_CLOCK_H_ */
|
#endif /* FSFW_TIMEMANAGER_CLOCK_H_ */
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
|
#include <ctime>
|
||||||
|
|
||||||
#include "fsfw/ipc/MutexGuard.h"
|
#include "fsfw/ipc/MutexGuard.h"
|
||||||
#include "fsfw/timemanager/Clock.h"
|
#include "fsfw/timemanager/Clock.h"
|
||||||
|
|
||||||
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval *tt) {
|
uint16_t Clock::leapSeconds = 0;
|
||||||
|
MutexIF* Clock::timeMutex = nullptr;
|
||||||
|
bool Clock::leapSecondsSet = false;
|
||||||
|
|
||||||
|
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
|
||||||
uint16_t leapSeconds;
|
uint16_t leapSeconds;
|
||||||
ReturnValue_t result = getLeapSeconds(&leapSeconds);
|
ReturnValue_t result = getLeapSeconds(&leapSeconds);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
@ -27,12 +33,16 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
|
|||||||
MutexGuard helper(timeMutex);
|
MutexGuard helper(timeMutex);
|
||||||
|
|
||||||
leapSeconds = leapSeconds_;
|
leapSeconds = leapSeconds_;
|
||||||
|
leapSecondsSet = true;
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getLeapSeconds(uint16_t *leapSeconds_) {
|
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
||||||
if (timeMutex == nullptr) {
|
if (not leapSecondsSet) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
if (checkOrCreateClockMutex() != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
MutexGuard helper(timeMutex);
|
MutexGuard helper(timeMutex);
|
||||||
@ -42,9 +52,32 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t *leapSeconds_) {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) {
|
||||||
|
struct tm* timeInfo;
|
||||||
|
// According to https://en.cppreference.com/w/c/chrono/gmtime, the implementation of gmtime_s
|
||||||
|
// in the Windows CRT is incompatible with the C standard but this should not be an issue for
|
||||||
|
// this implementation
|
||||||
|
ReturnValue_t result = checkOrCreateClockMutex();
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_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
|
||||||
|
timeInfo = gmtime(&from->tv_sec);
|
||||||
|
to->year = timeInfo->tm_year + 1900;
|
||||||
|
to->month = timeInfo->tm_mon + 1;
|
||||||
|
to->day = timeInfo->tm_mday;
|
||||||
|
to->hour = timeInfo->tm_hour;
|
||||||
|
to->minute = timeInfo->tm_min;
|
||||||
|
to->second = timeInfo->tm_sec;
|
||||||
|
to->usecond = from->tv_usec;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::checkOrCreateClockMutex() {
|
ReturnValue_t Clock::checkOrCreateClockMutex() {
|
||||||
if (timeMutex == nullptr) {
|
if (timeMutex == nullptr) {
|
||||||
MutexFactory *mutexFactory = MutexFactory::instance();
|
MutexFactory* mutexFactory = MutexFactory::instance();
|
||||||
if (mutexFactory == nullptr) {
|
if (mutexFactory == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ SpacePacket::SpacePacket(uint16_t packetDataLength, bool isTelecommand, uint16_t
|
|||||||
SpacePacket::~SpacePacket(void) {}
|
SpacePacket::~SpacePacket(void) {}
|
||||||
|
|
||||||
bool SpacePacket::addWholeData(const uint8_t* p_Data, uint32_t packet_size) {
|
bool SpacePacket::addWholeData(const uint8_t* p_Data, uint32_t packet_size) {
|
||||||
if (packet_size <= sizeof(this->data)) {
|
if (packet_size <= sizeof(this->localData)) {
|
||||||
memcpy(&this->localData.byteStream, p_Data, packet_size);
|
memcpy(this->localData.byteStream, p_Data, packet_size);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -95,7 +95,7 @@ class CommandingServiceBase : public SystemObject,
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
|
|
||||||
virtual uint16_t getIdentifier();
|
virtual uint16_t getIdentifier() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the requestQueue MessageQueueId_t
|
* Returns the requestQueue MessageQueueId_t
|
||||||
@ -104,7 +104,7 @@ class CommandingServiceBase : public SystemObject,
|
|||||||
*
|
*
|
||||||
* @return requestQueue messageQueueId_t
|
* @return requestQueue messageQueueId_t
|
||||||
*/
|
*/
|
||||||
virtual MessageQueueId_t getRequestQueue();
|
virtual MessageQueueId_t getRequestQueue() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the commandQueue MessageQueueId_t
|
* Returns the commandQueue MessageQueueId_t
|
||||||
|
@ -3,4 +3,5 @@ target_sources(${FSFW_TEST_TGT} PRIVATE
|
|||||||
testOpDivider.cpp
|
testOpDivider.cpp
|
||||||
testBitutil.cpp
|
testBitutil.cpp
|
||||||
testCRC.cpp
|
testCRC.cpp
|
||||||
|
testTimevalOperations.cpp
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,124 @@
|
|||||||
|
#include <fsfw/globalfunctions/timevalOperations.h>
|
||||||
|
|
||||||
|
#include <catch2/catch_approx.hpp>
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
#include "fsfw_tests/unit/CatchDefinitions.h"
|
||||||
|
|
||||||
|
TEST_CASE("TimevalTest", "[timevalOperations]") {
|
||||||
|
SECTION("Comparison") {
|
||||||
|
timeval t1;
|
||||||
|
t1.tv_sec = 1648227422;
|
||||||
|
t1.tv_usec = 123456;
|
||||||
|
timeval t2;
|
||||||
|
t2.tv_sec = 1648227422;
|
||||||
|
t2.tv_usec = 123456;
|
||||||
|
REQUIRE(t1 == t2);
|
||||||
|
REQUIRE(t2 == t1);
|
||||||
|
REQUIRE_FALSE(t1 != t2);
|
||||||
|
REQUIRE_FALSE(t2 != t1);
|
||||||
|
REQUIRE(t1 <= t2);
|
||||||
|
REQUIRE(t2 <= t1);
|
||||||
|
REQUIRE(t1 >= t2);
|
||||||
|
REQUIRE(t2 >= t1);
|
||||||
|
REQUIRE_FALSE(t1 < t2);
|
||||||
|
REQUIRE_FALSE(t2 < t1);
|
||||||
|
REQUIRE_FALSE(t1 > t2);
|
||||||
|
REQUIRE_FALSE(t2 > t1);
|
||||||
|
|
||||||
|
timeval t3;
|
||||||
|
t3.tv_sec = 1648227422;
|
||||||
|
t3.tv_usec = 123457;
|
||||||
|
REQUIRE_FALSE(t1 == t3);
|
||||||
|
REQUIRE(t1 != t3);
|
||||||
|
REQUIRE(t1 <= t3);
|
||||||
|
REQUIRE_FALSE(t3 <= t1);
|
||||||
|
REQUIRE_FALSE(t1 >= t3);
|
||||||
|
REQUIRE(t3 >= t1);
|
||||||
|
REQUIRE(t1 < t3);
|
||||||
|
REQUIRE_FALSE(t3 < t1);
|
||||||
|
REQUIRE_FALSE(t1 > t3);
|
||||||
|
REQUIRE(t3 > t1);
|
||||||
|
|
||||||
|
timeval t4;
|
||||||
|
t4.tv_sec = 1648227423;
|
||||||
|
t4.tv_usec = 123456;
|
||||||
|
REQUIRE_FALSE(t1 == t4);
|
||||||
|
REQUIRE(t1 != t4);
|
||||||
|
REQUIRE(t1 <= t4);
|
||||||
|
REQUIRE_FALSE(t4 <= t1);
|
||||||
|
REQUIRE_FALSE(t1 >= t4);
|
||||||
|
REQUIRE(t4 >= t1);
|
||||||
|
REQUIRE(t1 < t4);
|
||||||
|
REQUIRE_FALSE(t4 < t1);
|
||||||
|
REQUIRE_FALSE(t1 > t4);
|
||||||
|
REQUIRE(t4 > t1);
|
||||||
|
}
|
||||||
|
SECTION("Operators") {
|
||||||
|
timeval t1;
|
||||||
|
t1.tv_sec = 1648227422;
|
||||||
|
t1.tv_usec = 123456;
|
||||||
|
timeval t2;
|
||||||
|
t2.tv_sec = 1648227422;
|
||||||
|
t2.tv_usec = 123456;
|
||||||
|
timeval t3 = t1 - t2;
|
||||||
|
REQUIRE(t3.tv_sec == 0);
|
||||||
|
REQUIRE(t3.tv_usec == 0);
|
||||||
|
timeval t4 = t1 - t3;
|
||||||
|
REQUIRE(t4.tv_sec == 1648227422);
|
||||||
|
REQUIRE(t4.tv_usec == 123456);
|
||||||
|
timeval t5 = t3 - t1;
|
||||||
|
REQUIRE(t5.tv_sec == -1648227422);
|
||||||
|
REQUIRE(t5.tv_usec == -123456);
|
||||||
|
|
||||||
|
timeval t6;
|
||||||
|
t6.tv_sec = 1648227400;
|
||||||
|
t6.tv_usec = 999999;
|
||||||
|
|
||||||
|
timeval t7 = t6 + t1;
|
||||||
|
REQUIRE(t7.tv_sec == (1648227422ull + 1648227400ull + 1ull));
|
||||||
|
REQUIRE(t7.tv_usec == 123455);
|
||||||
|
|
||||||
|
timeval t8 = t1 - t6;
|
||||||
|
REQUIRE(t8.tv_sec == 1648227422 - 1648227400 - 1);
|
||||||
|
REQUIRE(t8.tv_usec == 123457);
|
||||||
|
|
||||||
|
double scalar = 2;
|
||||||
|
timeval t9 = t1 * scalar;
|
||||||
|
REQUIRE(t9.tv_sec == 3296454844);
|
||||||
|
REQUIRE(t9.tv_usec == 246912);
|
||||||
|
timeval t10 = scalar * t1;
|
||||||
|
REQUIRE(t10.tv_sec == 3296454844);
|
||||||
|
REQUIRE(t10.tv_usec == 246912);
|
||||||
|
timeval t11 = t6 * scalar;
|
||||||
|
REQUIRE(t11.tv_sec == (3296454800 + 1));
|
||||||
|
REQUIRE(t11.tv_usec == 999998);
|
||||||
|
|
||||||
|
timeval t12 = t1 / scalar;
|
||||||
|
REQUIRE(t12.tv_sec == 824113711);
|
||||||
|
REQUIRE(t12.tv_usec == 61728);
|
||||||
|
|
||||||
|
timeval t13 = t6 / scalar;
|
||||||
|
REQUIRE(t13.tv_sec == 824113700);
|
||||||
|
// Rounding issue
|
||||||
|
REQUIRE(t13.tv_usec == 499999);
|
||||||
|
|
||||||
|
double scalar2 = t9 / t1;
|
||||||
|
REQUIRE(scalar2 == Catch::Approx(2.0));
|
||||||
|
double scalar3 = t1 / t6;
|
||||||
|
REQUIRE(scalar3 == Catch::Approx(1.000000013));
|
||||||
|
double scalar4 = t3 / t1;
|
||||||
|
REQUIRE(scalar4 == Catch::Approx(0));
|
||||||
|
double scalar5 = t12 / t1;
|
||||||
|
REQUIRE(scalar5 == Catch::Approx(0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("timevalOperations::toTimeval") {
|
||||||
|
double seconds = 1648227422.123456;
|
||||||
|
timeval t1 = timevalOperations::toTimeval(seconds);
|
||||||
|
REQUIRE(t1.tv_sec == 1648227422);
|
||||||
|
// Allow 1 usec rounding tolerance
|
||||||
|
REQUIRE(t1.tv_usec >= 123455);
|
||||||
|
REQUIRE(t1.tv_usec <= 123457);
|
||||||
|
}
|
||||||
|
}
|
@ -4,8 +4,8 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "fsfw/ipc/MessageQueueBase.h"
|
|
||||||
#include "fsfw/ipc/CommandMessage.h"
|
#include "fsfw/ipc/CommandMessage.h"
|
||||||
|
#include "fsfw/ipc/MessageQueueBase.h"
|
||||||
#include "fsfw/ipc/MessageQueueIF.h"
|
#include "fsfw/ipc/MessageQueueIF.h"
|
||||||
#include "fsfw/ipc/MessageQueueMessage.h"
|
#include "fsfw/ipc/MessageQueueMessage.h"
|
||||||
#include "fsfw_tests/unit/CatchDefinitions.h"
|
#include "fsfw_tests/unit/CatchDefinitions.h"
|
||||||
@ -13,7 +13,7 @@
|
|||||||
class MessageQueueMockBase : public MessageQueueBase {
|
class MessageQueueMockBase : public MessageQueueBase {
|
||||||
public:
|
public:
|
||||||
MessageQueueMockBase()
|
MessageQueueMockBase()
|
||||||
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, nullptr) {}
|
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, nullptr) {}
|
||||||
|
|
||||||
uint8_t messageSentCounter = 0;
|
uint8_t messageSentCounter = 0;
|
||||||
bool messageSent = false;
|
bool messageSent = false;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||||
TestMessageQueue.cpp
|
TestMessageQueue.cpp
|
||||||
TestSemaphore.cpp
|
TestSemaphore.cpp
|
||||||
|
TestClock.cpp
|
||||||
)
|
)
|
||||||
|
86
tests/src/fsfw_tests/unit/osal/TestClock.cpp
Normal file
86
tests/src/fsfw_tests/unit/osal/TestClock.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include <fsfw/globalfunctions/timevalOperations.h>
|
||||||
|
#include <fsfw/timemanager/Clock.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <catch2/catch_approx.hpp>
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
#include "fsfw_tests/unit/CatchDefinitions.h"
|
||||||
|
|
||||||
|
TEST_CASE("OSAL::Clock Test", "[OSAL::Clock Test]") {
|
||||||
|
SECTION("Test getClock") {
|
||||||
|
timeval time;
|
||||||
|
ReturnValue_t result = Clock::getClock_timeval(&time);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
Clock::TimeOfDay_t timeOfDay;
|
||||||
|
result = Clock::getDateAndTime(&timeOfDay);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
timeval timeOfDayAsTimeval;
|
||||||
|
result = Clock::convertTimeOfDayToTimeval(&timeOfDay, &timeOfDayAsTimeval);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
// We require timeOfDayAsTimeval to be larger than time as it
|
||||||
|
// was request a few ns later
|
||||||
|
double difference = timevalOperations::toDouble(timeOfDayAsTimeval - time);
|
||||||
|
CHECK(difference >= 0.0);
|
||||||
|
CHECK(difference <= 0.005);
|
||||||
|
|
||||||
|
// Conversion in the other direction
|
||||||
|
Clock::TimeOfDay_t timevalAsTimeOfDay;
|
||||||
|
result = Clock::convertTimevalToTimeOfDay(&time, &timevalAsTimeOfDay);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
CHECK(timevalAsTimeOfDay.year <= timeOfDay.year);
|
||||||
|
// TODO We should write TimeOfDay operators!
|
||||||
|
}
|
||||||
|
SECTION("Leap seconds") {
|
||||||
|
uint16_t leapSeconds = 0;
|
||||||
|
ReturnValue_t result = Clock::getLeapSeconds(&leapSeconds);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_FAILED);
|
||||||
|
REQUIRE(leapSeconds == 0);
|
||||||
|
result = Clock::setLeapSeconds(18);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
result = Clock::getLeapSeconds(&leapSeconds);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
REQUIRE(leapSeconds == 18);
|
||||||
|
}
|
||||||
|
SECTION("usec Test") {
|
||||||
|
timeval timeAsTimeval;
|
||||||
|
ReturnValue_t result = Clock::getClock_timeval(&timeAsTimeval);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
uint64_t timeAsUsec = 0;
|
||||||
|
result = Clock::getClock_usecs(&timeAsUsec);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
double timeAsUsecDouble = static_cast<double>(timeAsUsec) / 1000000.0;
|
||||||
|
timeval timeAsUsecTimeval = timevalOperations::toTimeval(timeAsUsecDouble);
|
||||||
|
double difference = timevalOperations::toDouble(timeAsUsecTimeval - timeAsTimeval);
|
||||||
|
// We accept 5 ms difference
|
||||||
|
CHECK(difference >= 0.0);
|
||||||
|
CHECK(difference <= 0.005);
|
||||||
|
uint64_t timevalAsUint64 = static_cast<uint64_t>(timeAsTimeval.tv_sec) * 1000000ull +
|
||||||
|
static_cast<uint64_t>(timeAsTimeval.tv_usec);
|
||||||
|
CHECK((timeAsUsec - timevalAsUint64) >= 0);
|
||||||
|
CHECK((timeAsUsec - timevalAsUint64) <= (5 * 1000));
|
||||||
|
}
|
||||||
|
SECTION("Test j2000") {
|
||||||
|
double j2000;
|
||||||
|
timeval time;
|
||||||
|
time.tv_sec = 1648208539;
|
||||||
|
time.tv_usec = 0;
|
||||||
|
ReturnValue_t result = Clock::convertTimevalToJD2000(time, &j2000);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
double correctJ2000 = 2459663.98772 - 2451545.0;
|
||||||
|
CHECK(j2000 == Catch::Approx(correctJ2000).margin(1.2 * 1e-8));
|
||||||
|
}
|
||||||
|
SECTION("Convert to TT") {
|
||||||
|
timeval utcTime;
|
||||||
|
utcTime.tv_sec = 1648208539;
|
||||||
|
utcTime.tv_usec = 999000;
|
||||||
|
timeval tt;
|
||||||
|
ReturnValue_t result = Clock::setLeapSeconds(27);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
result = Clock::convertUTCToTT(utcTime, &tt);
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
CHECK(tt.tv_usec == 183000);
|
||||||
|
// The plus 1 is a own forced overflow of usecs
|
||||||
|
CHECK(tt.tv_sec == (1648208539 + 27 + 10 + 32 + 1));
|
||||||
|
}
|
||||||
|
}
|
@ -81,7 +81,8 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
|
|||||||
std::string timeAscii = "2022-12-31T23:59:59.123Z";
|
std::string timeAscii = "2022-12-31T23:59:59.123Z";
|
||||||
Clock::TimeOfDay_t timeTo;
|
Clock::TimeOfDay_t timeTo;
|
||||||
const uint8_t* timeChar = reinterpret_cast<const uint8_t*>(timeAscii.c_str());
|
const uint8_t* timeChar = reinterpret_cast<const uint8_t*>(timeAscii.c_str());
|
||||||
CCSDSTime::convertFromASCII(&timeTo, timeChar, timeAscii.length());
|
auto result = CCSDSTime::convertFromASCII(&timeTo, timeChar, timeAscii.length());
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
REQUIRE(timeTo.year == 2022);
|
REQUIRE(timeTo.year == 2022);
|
||||||
REQUIRE(timeTo.month == 12);
|
REQUIRE(timeTo.month == 12);
|
||||||
REQUIRE(timeTo.day == 31);
|
REQUIRE(timeTo.day == 31);
|
||||||
@ -89,6 +90,19 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
|
|||||||
REQUIRE(timeTo.minute == 59);
|
REQUIRE(timeTo.minute == 59);
|
||||||
REQUIRE(timeTo.second == 59);
|
REQUIRE(timeTo.second == 59);
|
||||||
REQUIRE(timeTo.usecond == Catch::Approx(123000));
|
REQUIRE(timeTo.usecond == Catch::Approx(123000));
|
||||||
|
|
||||||
|
std::string timeAscii2 = "2022-365T23:59:59.123Z";
|
||||||
|
const uint8_t* timeChar2 = reinterpret_cast<const uint8_t*>(timeAscii2.c_str());
|
||||||
|
Clock::TimeOfDay_t timeTo2;
|
||||||
|
result = CCSDSTime::convertFromCcsds(&timeTo2, timeChar2, timeAscii2.length());
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
REQUIRE(timeTo2.year == 2022);
|
||||||
|
REQUIRE(timeTo2.month == 12);
|
||||||
|
REQUIRE(timeTo2.day == 31);
|
||||||
|
REQUIRE(timeTo2.hour == 23);
|
||||||
|
REQUIRE(timeTo2.minute == 59);
|
||||||
|
REQUIRE(timeTo2.second == 59);
|
||||||
|
REQUIRE(timeTo2.usecond == Catch::Approx(123000));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("CDS Conversions") {
|
SECTION("CDS Conversions") {
|
||||||
@ -119,6 +133,7 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
|
|||||||
CHECK(cdsTime.msDay_h == 0xE0);
|
CHECK(cdsTime.msDay_h == 0xE0);
|
||||||
CHECK(cdsTime.msDay_l == 0xC5);
|
CHECK(cdsTime.msDay_l == 0xC5);
|
||||||
CHECK(cdsTime.msDay_ll == 0xC3);
|
CHECK(cdsTime.msDay_ll == 0xC3);
|
||||||
|
CHECK(cdsTime.pField == CCSDSTime::P_FIELD_CDS_SHORT);
|
||||||
|
|
||||||
// Conversion back to timeval
|
// Conversion back to timeval
|
||||||
timeval timeReturnAsTimeval;
|
timeval timeReturnAsTimeval;
|
||||||
@ -128,5 +143,77 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
|
|||||||
timeval difference = timeAsTimeval - timeReturnAsTimeval;
|
timeval difference = timeAsTimeval - timeReturnAsTimeval;
|
||||||
CHECK(difference.tv_usec == 456);
|
CHECK(difference.tv_usec == 456);
|
||||||
CHECK(difference.tv_sec == 0);
|
CHECK(difference.tv_sec == 0);
|
||||||
|
|
||||||
|
Clock::TimeOfDay_t timeReturnAsTimeOfDay;
|
||||||
|
result = CCSDSTime::convertFromCDS(&timeReturnAsTimeOfDay, &cdsTime);
|
||||||
|
CHECK(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
CHECK(timeReturnAsTimeOfDay.year == 2020);
|
||||||
|
CHECK(timeReturnAsTimeOfDay.month == 2);
|
||||||
|
CHECK(timeReturnAsTimeOfDay.day == 29);
|
||||||
|
CHECK(timeReturnAsTimeOfDay.hour == 13);
|
||||||
|
CHECK(timeReturnAsTimeOfDay.minute == 24);
|
||||||
|
CHECK(timeReturnAsTimeOfDay.second == 45);
|
||||||
|
// micro seconds precision is lost
|
||||||
|
CHECK(timeReturnAsTimeOfDay.usecond == 123000);
|
||||||
|
|
||||||
|
Clock::TimeOfDay_t timeReturnAsTodFromBuffer;
|
||||||
|
const uint8_t* buffer = reinterpret_cast<const uint8_t*>(&cdsTime);
|
||||||
|
result = CCSDSTime::convertFromCDS(&timeReturnAsTodFromBuffer, buffer, sizeof(cdsTime));
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
CHECK(timeReturnAsTodFromBuffer.year == time.year);
|
||||||
|
CHECK(timeReturnAsTodFromBuffer.month == time.month);
|
||||||
|
CHECK(timeReturnAsTodFromBuffer.day == time.day);
|
||||||
|
CHECK(timeReturnAsTodFromBuffer.hour == time.hour);
|
||||||
|
CHECK(timeReturnAsTodFromBuffer.minute == time.minute);
|
||||||
|
CHECK(timeReturnAsTodFromBuffer.second == time.second);
|
||||||
|
CHECK(timeReturnAsTodFromBuffer.usecond == 123000);
|
||||||
|
|
||||||
|
Clock::TimeOfDay_t todFromCCSDS;
|
||||||
|
result = CCSDSTime::convertFromCcsds(&todFromCCSDS, buffer, sizeof(cdsTime));
|
||||||
|
CHECK(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
CHECK(todFromCCSDS.year == time.year);
|
||||||
|
CHECK(todFromCCSDS.month == time.month);
|
||||||
|
CHECK(todFromCCSDS.day == time.day);
|
||||||
|
CHECK(todFromCCSDS.hour == time.hour);
|
||||||
|
CHECK(todFromCCSDS.minute == time.minute);
|
||||||
|
CHECK(todFromCCSDS.second == time.second);
|
||||||
|
CHECK(todFromCCSDS.usecond == 123000);
|
||||||
|
}
|
||||||
|
SECTION("CUC") {
|
||||||
|
timeval to;
|
||||||
|
// seconds = 0x771E960F, microseconds = 0x237
|
||||||
|
// microseconds = 567000
|
||||||
|
// This gives 37158.912 1/65536 seconds -> rounded to 37159 -> 0x9127
|
||||||
|
// This results in -> 567001 us
|
||||||
|
std::array<uint8_t, 7> cucBuffer = {
|
||||||
|
CCSDSTime::P_FIELD_CUC_6B_CCSDS, 0x77, 0x1E, 0x96, 0x0F, 0x91, 0x27};
|
||||||
|
size_t foundLength = 0;
|
||||||
|
auto result = CCSDSTime::convertFromCUC(&to, cucBuffer.data(), &foundLength, cucBuffer.size());
|
||||||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
REQUIRE(foundLength == 7);
|
||||||
|
REQUIRE(to.tv_sec == 1619801999); // TAI (no leap seconds)
|
||||||
|
REQUIRE(to.tv_usec == 567001);
|
||||||
|
|
||||||
|
Clock::TimeOfDay_t tod;
|
||||||
|
result = CCSDSTime::convertFromCUC(&tod, cucBuffer.data(), cucBuffer.size());
|
||||||
|
// This test must be changed if this is ever going to be implemented
|
||||||
|
REQUIRE(result == CCSDSTime::UNSUPPORTED_TIME_FORMAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("CCSDS Failures") {
|
||||||
|
Clock::TimeOfDay_t time;
|
||||||
|
time.year = 2020;
|
||||||
|
time.month = 12;
|
||||||
|
time.day = 32;
|
||||||
|
time.hour = 13;
|
||||||
|
time.minute = 24;
|
||||||
|
time.second = 45;
|
||||||
|
time.usecond = 123456;
|
||||||
|
CCSDSTime::Ccs_mseconds to;
|
||||||
|
auto result = CCSDSTime::convertToCcsds(&to, &time);
|
||||||
|
REQUIRE(result == CCSDSTime::INVALID_TIME_FORMAT);
|
||||||
|
CCSDSTime::Ccs_seconds to2;
|
||||||
|
result = CCSDSTime::convertToCcsds(&to2, &time);
|
||||||
|
REQUIRE(result == CCSDSTime::INVALID_TIME_FORMAT);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user