Merge branch 'development' into mueller/possible-ring-buffer-fix
This commit is contained in:
commit
e1604b292c
12
CHANGELOG.md
12
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
|
||||||
@ -52,9 +55,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
||||||
- Added ETL dependency and improved library dependency management
|
- Added ETL dependency and improved library dependency management
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
|
||||||
|
- `Subsystem`: New API to add table and sequence entries
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
- TCP TMTC Server: `MutexGuard` was not created properly in
|
||||||
|
`TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)` call.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/618
|
||||||
|
- Fix infinite recursion in `prepareHealthSetReply` of PUS Health Service 201.
|
||||||
|
Is not currently used right now but might be used in the future
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/617
|
||||||
|
- Move some CMake directives further up top so they are not ignored
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/621
|
||||||
- Small bugfix in STM32 HAL for SPI
|
- 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
|
- HAL GPIO: Improved error checking in `LinuxLibgpioIF::configureGpios(...)`. If a GPIO
|
||||||
|
@ -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') {
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define FIXEDARRAYLIST_H_
|
#define FIXEDARRAYLIST_H_
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include "ArrayList.h"
|
#include "ArrayList.h"
|
||||||
/**
|
/**
|
||||||
@ -9,10 +10,8 @@
|
|||||||
*/
|
*/
|
||||||
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)
|
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
||||||
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
|
|
||||||
private:
|
private:
|
||||||
T data[MAX_SIZE];
|
T data[MAX_SIZE];
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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_ */
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#elif defined(PLATFORM_UNIX)
|
#elif defined(PLATFORM_UNIX)
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
||||||
@ -29,7 +31,7 @@ TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
|
|||||||
: SystemObject(objectId),
|
: SystemObject(objectId),
|
||||||
tmtcBridgeId(tmtcTcpBridge),
|
tmtcBridgeId(tmtcTcpBridge),
|
||||||
receptionMode(receptionMode),
|
receptionMode(receptionMode),
|
||||||
tcpConfig(customTcpServerPort),
|
tcpConfig(std::move(customTcpServerPort)),
|
||||||
receptionBuffer(receptionBufferSize),
|
receptionBuffer(receptionBufferSize),
|
||||||
ringBuffer(ringBufferSize, true) {}
|
ringBuffer(ringBufferSize, true) {}
|
||||||
|
|
||||||
@ -103,7 +105,7 @@ ReturnValue_t TcpTmTcServer::initialize() {
|
|||||||
|
|
||||||
TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
||||||
|
|
||||||
ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
[[noreturn]] ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
||||||
using namespace tcpip;
|
using namespace tcpip;
|
||||||
// If a connection is accepted, the corresponding socket will be assigned to the new socket
|
// If a connection is accepted, the corresponding socket will be assigned to the new socket
|
||||||
socket_t connSocket = 0;
|
socket_t connSocket = 0;
|
||||||
@ -138,7 +140,6 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
|||||||
closeSocket(connSocket);
|
closeSocket(connSocket);
|
||||||
connSocket = 0;
|
connSocket = 0;
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() {
|
ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() {
|
||||||
@ -159,7 +160,7 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int retval = recv(connSocket, reinterpret_cast<char*>(receptionBuffer.data()),
|
ssize_t retval = recv(connSocket, reinterpret_cast<char*>(receptionBuffer.data()),
|
||||||
receptionBuffer.capacity(), tcpConfig.tcpFlags);
|
receptionBuffer.capacity(), tcpConfig.tcpFlags);
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
size_t availableReadData = ringBuffer.getAvailableReadData();
|
size_t availableReadData = ringBuffer.getAvailableReadData();
|
||||||
@ -252,17 +253,17 @@ ReturnValue_t TcpTmTcServer::handleTcReception(uint8_t* spacePacket, size_t pack
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TcpTmTcServer::getTcpPort() const { return tcpConfig.tcpPort; }
|
const std::string& TcpTmTcServer::getTcpPort() const { return tcpConfig.tcpPort; }
|
||||||
|
|
||||||
void TcpTmTcServer::setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds) {
|
void TcpTmTcServer::setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds_) {
|
||||||
this->validPacketIds = validPacketIds;
|
this->validPacketIds = std::move(validPacketIds_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TcpTmTcServer::TcpConfig& TcpTmTcServer::getTcpConfigStruct() { return tcpConfig; }
|
TcpTmTcServer::TcpConfig& TcpTmTcServer::getTcpConfigStruct() { return tcpConfig; }
|
||||||
|
|
||||||
ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) {
|
ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) {
|
||||||
// Access to the FIFO is mutex protected because it is filled by the bridge
|
// Access to the FIFO is mutex protected because it is filled by the bridge
|
||||||
MutexGuard(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs);
|
MutexGuard mg(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs);
|
||||||
store_address_t storeId;
|
store_address_t storeId;
|
||||||
while ((not tmtcBridge->tmFifo->empty()) and
|
while ((not tmtcBridge->tmFifo->empty()) and
|
||||||
(tmtcBridge->packetSentCounter < tmtcBridge->sentPacketsPerCycle)) {
|
(tmtcBridge->packetSentCounter < tmtcBridge->sentPacketsPerCycle)) {
|
||||||
@ -283,7 +284,7 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)
|
|||||||
#endif
|
#endif
|
||||||
arrayprinter::print(storeAccessor.data(), storeAccessor.size());
|
arrayprinter::print(storeAccessor.data(), storeAccessor.size());
|
||||||
}
|
}
|
||||||
int retval = send(connSocket, reinterpret_cast<const char*>(storeAccessor.data()),
|
ssize_t retval = send(connSocket, reinterpret_cast<const char*>(storeAccessor.data()),
|
||||||
storeAccessor.size(), tcpConfig.tcpTmFlags);
|
storeAccessor.size(), tcpConfig.tcpTmFlags);
|
||||||
if (retval == static_cast<int>(storeAccessor.size())) {
|
if (retval == static_cast<int>(storeAccessor.size())) {
|
||||||
// Packet sent, clear FIFO entry
|
// Packet sent, clear FIFO entry
|
||||||
@ -339,6 +340,9 @@ ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) {
|
|||||||
size_t foundSize = 0;
|
size_t foundSize = 0;
|
||||||
size_t readLen = 0;
|
size_t readLen = 0;
|
||||||
while (readLen < readAmount) {
|
while (readLen < readAmount) {
|
||||||
|
if(spacePacketParser == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
result =
|
result =
|
||||||
spacePacketParser->parseSpacePackets(bufPtrPtr, readAmount, startIdx, foundSize, readLen);
|
spacePacketParser->parseSpacePackets(bufPtrPtr, readAmount, startIdx, foundSize, readLen);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class TcpTmTcBridge;
|
class TcpTmTcBridge;
|
||||||
@ -44,7 +45,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
|
|
||||||
struct TcpConfig {
|
struct TcpConfig {
|
||||||
public:
|
public:
|
||||||
TcpConfig(std::string tcpPort) : tcpPort(tcpPort) {}
|
explicit TcpConfig(std::string tcpPort) : tcpPort(std::move(tcpPort)) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Passed to the recv call
|
* Passed to the recv call
|
||||||
@ -84,7 +85,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
size_t ringBufferSize = RING_BUFFER_SIZE,
|
size_t ringBufferSize = RING_BUFFER_SIZE,
|
||||||
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
|
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
|
||||||
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
|
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
|
||||||
virtual ~TcpTmTcServer();
|
~TcpTmTcServer() override;
|
||||||
|
|
||||||
void enableWiretapping(bool enable);
|
void enableWiretapping(bool enable);
|
||||||
|
|
||||||
@ -97,10 +98,10 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
void setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds);
|
void setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds);
|
||||||
|
|
||||||
ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
[[noreturn]] ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
ReturnValue_t initializeAfterTaskCreation() override;
|
ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
std::string getTcpPort() const;
|
[[nodiscard]] const std::string& getTcpPort() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StorageManagerIF* tcStore = nullptr;
|
StorageManagerIF* tcStore = nullptr;
|
||||||
@ -115,7 +116,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
|
|
||||||
ReceptionModes receptionMode;
|
ReceptionModes receptionMode;
|
||||||
TcpConfig tcpConfig;
|
TcpConfig tcpConfig;
|
||||||
struct sockaddr tcpAddress;
|
struct sockaddr tcpAddress = {};
|
||||||
socket_t listenerTcpSocket = 0;
|
socket_t listenerTcpSocket = 0;
|
||||||
|
|
||||||
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;
|
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;
|
||||||
|
@ -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.
|
||||||
|
@ -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()
|
@ -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}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -13,8 +13,6 @@ CService201HealthCommanding::CService201HealthCommanding(object_id_t objectId, u
|
|||||||
: CommandingServiceBase(objectId, apid, serviceId, numParallelCommands, commandTimeoutSeconds) {
|
: CommandingServiceBase(objectId, apid, serviceId, numParallelCommands, commandTimeoutSeconds) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CService201HealthCommanding::~CService201HealthCommanding() {}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) {
|
ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) {
|
||||||
switch (subservice) {
|
switch (subservice) {
|
||||||
case (Subservice::COMMAND_SET_HEALTH):
|
case (Subservice::COMMAND_SET_HEALTH):
|
||||||
@ -43,8 +41,8 @@ ReturnValue_t CService201HealthCommanding::getMessageQueueAndObject(uint8_t subs
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
||||||
MessageQueueId_t *messageQueueToSet, object_id_t *objectId) {
|
MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
|
||||||
HasHealthIF *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
||||||
if (destination == nullptr) {
|
if (destination == nullptr) {
|
||||||
return CommandingServiceBase::INVALID_OBJECT;
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
}
|
}
|
||||||
@ -77,6 +75,10 @@ ReturnValue_t CService201HealthCommanding::prepareCommand(CommandMessage *messag
|
|||||||
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
|
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default: {
|
||||||
|
// Should never happen, subservice was already checked
|
||||||
|
result = RETURN_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -95,10 +97,9 @@ ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *rep
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Not used for now, health state already reported by event
|
// Not used for now, health state already reported by event
|
||||||
ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(const CommandMessage *reply) {
|
[[maybe_unused]] ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(const CommandMessage *reply) {
|
||||||
prepareHealthSetReply(reply);
|
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
||||||
uint8_t health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
||||||
uint8_t oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
|
||||||
HealthSetReply healthSetReply(health, oldHealth);
|
HealthSetReply healthSetReply(health, oldHealth);
|
||||||
return sendTmPacket(Subservice::REPLY_HEALTH_SET, &healthSetReply);
|
return sendTmPacket(Subservice::REPLY_HEALTH_SET, &healthSetReply);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
|
|
||||||
#include "../tmtcservices/CommandingServiceBase.h"
|
#include "fsfw/tmtcservices/CommandingServiceBase.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom PUS service to set health of all objects
|
* @brief Custom PUS service to set health of all objects
|
||||||
@ -21,7 +21,7 @@ class CService201HealthCommanding : public CommandingServiceBase {
|
|||||||
public:
|
public:
|
||||||
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
||||||
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
|
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
|
||||||
virtual ~CService201HealthCommanding();
|
~CService201HealthCommanding() override = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* CSB abstract function implementations */
|
/* CSB abstract function implementations */
|
||||||
@ -38,12 +38,10 @@ class CService201HealthCommanding : public CommandingServiceBase {
|
|||||||
bool *isStep) override;
|
bool *isStep) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ReturnValue_t checkAndAcquireTargetID(object_id_t *objectIdToSet, const uint8_t *tcData,
|
static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
||||||
size_t tcDataLen);
|
const object_id_t *objectId);
|
||||||
ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
|
||||||
object_id_t *objectId);
|
|
||||||
|
|
||||||
ReturnValue_t prepareHealthSetReply(const CommandMessage *reply);
|
[[maybe_unused]] ReturnValue_t prepareHealthSetReply(const CommandMessage *reply);
|
||||||
|
|
||||||
enum Subservice {
|
enum Subservice {
|
||||||
//! [EXPORT] : [TC] Set health of target object
|
//! [EXPORT] : [TC] Set health of target object
|
||||||
|
@ -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];
|
||||||
@ -299,6 +307,11 @@ void Subsystem::replyToCommand(ReturnValue_t status, uint32_t parameter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Subsystem::addSequence(SequenceEntry sequence) {
|
||||||
|
return addSequence(sequence.table, sequence.mode, sequence.fallbackMode, sequence.inStore,
|
||||||
|
sequence.preInit);
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t Subsystem::addSequence(ArrayList<ModeListEntry> *sequence, Mode_t id,
|
ReturnValue_t Subsystem::addSequence(ArrayList<ModeListEntry> *sequence, Mode_t id,
|
||||||
Mode_t fallbackSequence, bool inStore, bool preInit) {
|
Mode_t fallbackSequence, bool inStore, bool preInit) {
|
||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
@ -342,6 +355,10 @@ ReturnValue_t Subsystem::addSequence(ArrayList<ModeListEntry> *sequence, Mode_t
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Subsystem::addTable(TableEntry table) {
|
||||||
|
return addTable(table.table, table.mode, table.inStore, table.preInit);
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t Subsystem::addTable(ArrayList<ModeListEntry> *table, Mode_t id, bool inStore,
|
ReturnValue_t Subsystem::addTable(ArrayList<ModeListEntry> *table, Mode_t id, bool inStore,
|
||||||
bool preInit) {
|
bool preInit) {
|
||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
@ -450,6 +467,7 @@ ReturnValue_t Subsystem::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mode = initialMode;
|
mode = initialMode;
|
||||||
|
submode = initSubmode;
|
||||||
|
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
@ -587,7 +605,10 @@ ReturnValue_t Subsystem::checkObjectConnections() {
|
|||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Subsystem::setInitialMode(Mode_t mode) { initialMode = mode; }
|
void Subsystem::setInitialMode(Mode_t mode, Submode_t submode) {
|
||||||
|
this->initialMode = mode;
|
||||||
|
this->initSubmode = submode;
|
||||||
|
}
|
||||||
|
|
||||||
void Subsystem::cantKeepMode() {
|
void Subsystem::cantKeepMode() {
|
||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
|
@ -1,16 +1,37 @@
|
|||||||
#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"
|
||||||
|
|
||||||
|
struct TableSequenceBase {
|
||||||
|
public:
|
||||||
|
TableSequenceBase(Mode_t mode, ArrayList<ModeListEntry> *table) : mode(mode), table(table){};
|
||||||
|
Mode_t mode;
|
||||||
|
ArrayList<ModeListEntry> *table;
|
||||||
|
bool inStore = false;
|
||||||
|
bool preInit = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TableEntry : public TableSequenceBase {
|
||||||
|
public:
|
||||||
|
TableEntry(Mode_t mode, ArrayList<ModeListEntry> *table) : TableSequenceBase(mode, table){};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SequenceEntry : public TableSequenceBase {
|
||||||
|
public:
|
||||||
|
SequenceEntry(Mode_t mode, ArrayList<ModeListEntry> *table, Mode_t fallbackMode)
|
||||||
|
: TableSequenceBase(mode, table), fallbackMode(fallbackMode) {}
|
||||||
|
|
||||||
|
Mode_t fallbackMode;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief TODO: documentation missing
|
* @brief TODO: documentation missing
|
||||||
* @details
|
* @details
|
||||||
@ -45,13 +66,15 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF {
|
|||||||
uint32_t maxNumberOfTables);
|
uint32_t maxNumberOfTables);
|
||||||
virtual ~Subsystem();
|
virtual ~Subsystem();
|
||||||
|
|
||||||
|
ReturnValue_t addSequence(SequenceEntry sequence);
|
||||||
ReturnValue_t addSequence(ArrayList<ModeListEntry> *sequence, Mode_t id, Mode_t fallbackSequence,
|
ReturnValue_t addSequence(ArrayList<ModeListEntry> *sequence, Mode_t id, Mode_t fallbackSequence,
|
||||||
bool inStore = true, bool preInit = true);
|
bool inStore = true, bool preInit = true);
|
||||||
|
|
||||||
|
ReturnValue_t addTable(TableEntry table);
|
||||||
ReturnValue_t addTable(ArrayList<ModeListEntry> *table, Mode_t id, bool inStore = true,
|
ReturnValue_t addTable(ArrayList<ModeListEntry> *table, Mode_t id, bool inStore = true,
|
||||||
bool preInit = true);
|
bool preInit = true);
|
||||||
|
|
||||||
void setInitialMode(Mode_t mode);
|
void setInitialMode(Mode_t mode, Submode_t submode = SUBMODE_NONE);
|
||||||
|
|
||||||
virtual ReturnValue_t initialize() override;
|
virtual ReturnValue_t initialize() override;
|
||||||
|
|
||||||
@ -90,6 +113,7 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF {
|
|||||||
Submode_t targetSubmode;
|
Submode_t targetSubmode;
|
||||||
|
|
||||||
Mode_t initialMode = 0;
|
Mode_t initialMode = 0;
|
||||||
|
Submode_t initSubmode = SUBMODE_NONE;
|
||||||
|
|
||||||
HybridIterator<ModeListEntry> currentSequenceIterator;
|
HybridIterator<ModeListEntry> currentSequenceIterator;
|
||||||
|
|
||||||
@ -127,18 +151,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) {
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -588,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
|
||||||
*
|
*
|
||||||
|
@ -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
|
||||||
@ -166,7 +166,7 @@ class CommandingServiceBase : public SystemObject,
|
|||||||
* @param objectId Target object ID
|
* @param objectId Target object ID
|
||||||
* @return
|
* @return
|
||||||
* - @c RETURN_OK to generate a verification start message
|
* - @c RETURN_OK to generate a verification start message
|
||||||
* - @c EXECUTION_COMPELTE Fire-and-forget command. Generate a completion
|
* - @c EXECUTION_COMPLETE Fire-and-forget command. Generate a completion
|
||||||
* verification message.
|
* verification message.
|
||||||
* - @c Anything else rejects the packets and generates a start failure
|
* - @c Anything else rejects the packets and generates a start failure
|
||||||
* verification.
|
* verification.
|
||||||
|
@ -179,6 +179,27 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
|
|||||||
CHECK(todFromCCSDS.second == time.second);
|
CHECK(todFromCCSDS.second == time.second);
|
||||||
CHECK(todFromCCSDS.usecond == 123000);
|
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") {
|
SECTION("CCSDS Failures") {
|
||||||
Clock::TimeOfDay_t time;
|
Clock::TimeOfDay_t time;
|
||||||
time.year = 2020;
|
time.year = 2020;
|
||||||
|
Loading…
Reference in New Issue
Block a user