Merge remote-tracking branch 'upstream/development' into eive/develop

This commit is contained in:
Robin Müller 2022-05-02 16:15:27 +02:00
commit 7f6c8b8b12
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
33 changed files with 212 additions and 149 deletions

View File

@ -16,11 +16,12 @@ set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING
set(FSFW_ETL_LIB_VERSION ${FSFW_ETL_LIB_MAJOR_VERSION}.27.3 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"
) )
@ -110,9 +111,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)
@ -135,23 +134,36 @@ endif()
message(STATUS "Finding and/or providing etl library with version ${FSFW_ETL_LIB_MAJOR_VERSION}") message(STATUS "Finding and/or providing etl library with version ${FSFW_ETL_LIB_MAJOR_VERSION}")
# Check whether the user has already installed ETL first # Check whether the user has already installed ETL first
# find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET) find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET)
# Not installed, so use FetchContent to download and provide etl # Not installed, so use FetchContent to download and provide etl
# if(NOT ${FSFW_ETL_LIB_NAME}_FOUND) if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
message(STATUS message(STATUS
"No etl installation was found with find_package. Installing and providing " "No ETL installation was found with find_package. Installing and providing "
"etl with FetchContent" "etl with FindPackage"
) )
include(FetchContent) include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_NAME}
GIT_REPOSITORY https://github.com/ETLCPP/etl GIT_REPOSITORY https://github.com/ETLCPP/etl
GIT_TAG ${FSFW_ETL_LIB_VERSION} GIT_TAG ${FSFW_ETL_LIB_VERSION}
) )
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_ETL_LIB_NAME})
endif()
FetchContent_MakeAvailable(${FSFW_ETL_LIB_NAME}) # The documentation for FetchContent recommends declaring all the dependencies
# endif() # 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()
set(FSFW_CORE_INC_PATH "inc") set(FSFW_CORE_INC_PATH "inc")
@ -414,7 +426,7 @@ target_compile_options(${LIB_FSFW_NAME} PRIVATE
) )
target_link_libraries(${LIB_FSFW_NAME} PRIVATE target_link_libraries(${LIB_FSFW_NAME} PRIVATE
etl ${FSFW_ETL_LINK_TARGET}
${FSFW_ADDITIONAL_LINK_LIBS} ${FSFW_ADDITIONAL_LINK_LIBS}
) )

View File

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

View File

@ -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') {

View File

@ -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)

View File

@ -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)

View File

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

View File

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

View File

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

View File

@ -10,7 +10,7 @@ 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) { if (iter != nullptr) {
value = iter->value; value = iter->value;
} }

View File

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

View File

@ -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,

View File

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

View File

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

View File

@ -166,7 +166,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
@ -176,7 +176,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.
@ -1068,11 +1068,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.

View File

@ -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()) {

View File

@ -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 {

View File

@ -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();

View File

@ -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_ */

View File

@ -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) {

View File

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

View File

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

View File

@ -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.

View File

@ -1,5 +1,4 @@
target_sources(${LIB_FSFW_NAME} target_sources(${LIB_FSFW_NAME} PRIVATE
PRIVATE
Clock.cpp Clock.cpp
FixedTimeslotTask.cpp FixedTimeslotTask.cpp
MessageQueue.cpp MessageQueue.cpp
@ -16,9 +15,13 @@ target_sources(${LIB_FSFW_NAME}
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
rt
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
) )
if(NOT APPLE)
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
rt
)
endif()
endif() endif()

View File

@ -18,12 +18,12 @@ target_sources(${LIB_FSFW_NAME} PRIVATE
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}
)

View File

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

View File

@ -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 {

View File

@ -155,18 +155,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);

View File

@ -137,9 +137,9 @@ class SubsystemBase : public SystemObject,
virtual void getMode(Mode_t *mode, Submode_t *submode) override; 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();
}; };

View File

@ -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.

View File

@ -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
* *

View File

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

View File

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

View File

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