From ec212d9fcf45410507110d5b87f00af71846d037 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Jul 2020 13:26:58 +0200 Subject: [PATCH 01/20] new fifo init --- container/FIFO.h | 88 ++++++++---------------------------------- container/FIFOBase.h | 59 ++++++++++++++++++++++++++++ container/FIFOBase.tpp | 76 ++++++++++++++++++++++++++++++++++++ container/StaticFIFO.h | 23 +++++++++++ 4 files changed, 174 insertions(+), 72 deletions(-) create mode 100644 container/FIFOBase.h create mode 100644 container/FIFOBase.tpp create mode 100644 container/StaticFIFO.h diff --git a/container/FIFO.h b/container/FIFO.h index f70c78b0..217ddbca 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -1,82 +1,26 @@ -#ifndef FIFO_H_ -#define FIFO_H_ +#ifndef FRAMEWORK_CONTAINER_FIFO_H_ +#define FRAMEWORK_CONTAINER_FIFO_H_ -#include +#include +#include /** - * @brief Simple First-In-First-Out data structure + * @brief Simple First-In-First-Out data structure. The maximum size + * can be set in the constructor. THe public interface of + * FIFOBase exposes the user interface for the FIFO. * @tparam T Entry Type * @tparam capacity Maximum capacity */ -template -class FIFO { -private: - uint8_t readIndex, writeIndex, currentSize; - T data[capacity]; - - uint8_t next(uint8_t current) { - ++current; - if (current == capacity) { - current = 0; - } - return current; - } +template +class FIFO: public FIFOBase { public: - FIFO() : - readIndex(0), writeIndex(0), currentSize(0) { - } + FIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity) { + values.reserve(maxCapacity); + values.resize(maxCapacity); + }; - bool empty() { - return (currentSize == 0); - } - - bool full() { - return (currentSize == capacity); - } - - uint8_t size(){ - return currentSize; - } - - ReturnValue_t insert(T value) { - if (full()) { - return FULL; - } else { - data[writeIndex] = value; - writeIndex = next(writeIndex); - ++currentSize; - return HasReturnvaluesIF::RETURN_OK; - } - } - - ReturnValue_t retrieve(T *value) { - if (empty()) { - return EMPTY; - } else { - *value = data[readIndex]; - readIndex = next(readIndex); - --currentSize; - return HasReturnvaluesIF::RETURN_OK; - } - } - - ReturnValue_t peek(T * value) { - if(empty()) { - return EMPTY; - } else { - *value = data[readIndex]; - return HasReturnvaluesIF::RETURN_OK; - } - } - - ReturnValue_t pop() { - T value; - return this->retrieve(&value); - } - - static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS; - static const ReturnValue_t FULL = MAKE_RETURN_CODE(1); - static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2); +private: + std::vector values; }; -#endif /* FIFO_H_ */ +#endif /* FRAMEWORK_CONTAINER_FIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h new file mode 100644 index 00000000..c6a74d2f --- /dev/null +++ b/container/FIFOBase.h @@ -0,0 +1,59 @@ +#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_ +#define FRAMEWORK_CONTAINER_FIFOBASE_H_ + +#include +#include + +template +class FIFOBase { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS; + static const ReturnValue_t FULL = MAKE_RETURN_CODE(1); + static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2); + + + /** Default ctor, no input arguments required. */ + FIFOBase(T* values, const size_t maxCapacity); + + /** + * Insert value into FIFO + * @param value + * @return + */ + ReturnValue_t insert(T value); + /** + * Retrieve item from FIFO. This removes the item from the FIFO. + * @param value + * @return + */ + ReturnValue_t retrieve(T *value); + /** + * Retrieve item from FIFO without removing it from FIFO. + * @param value + * @return + */ + ReturnValue_t peek(T * value); + /** + * Remove item from FIFO. + * @return + */ + ReturnValue_t pop(); + + bool empty(); + bool full(); + size_t size(); + +private: + T* values; + size_t maxCapacity; + + size_t readIndex = 0; + size_t writeIndex = 0; + size_t currentSize = 0; + + size_t next(size_t current); +}; + +#include + +#endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */ diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp new file mode 100644 index 00000000..011ce6de --- /dev/null +++ b/container/FIFOBase.tpp @@ -0,0 +1,76 @@ +#ifndef FRAMEWORK_CONTAINER_FIFOBASE_TPP_ +#define FRAMEWORK_CONTAINER_FIFOBASE_TPP_ + +#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_ +#error Include FIFOBase.h before FIFOBase.tpp! +#endif + +template +inline FIFOBase::FIFOBase(T* values, const size_t maxCapacity): + values(values), maxCapacity(maxCapacity) {}; + +template +inline ReturnValue_t FIFOBase::insert(T value) { + if (full()) { + return FULL; + } else { + values[writeIndex] = value; + writeIndex = next(writeIndex); + ++currentSize; + return HasReturnvaluesIF::RETURN_OK; + } +}; + +template +inline ReturnValue_t FIFOBase::retrieve(T* value) { + if (empty()) { + return EMPTY; + } else { + *value = values[readIndex]; + readIndex = next(readIndex); + --currentSize; + return HasReturnvaluesIF::RETURN_OK; + } +}; + +template +inline ReturnValue_t FIFOBase::peek(T* value) { + if(empty()) { + return EMPTY; + } else { + *value = values[readIndex]; + return HasReturnvaluesIF::RETURN_OK; + } +}; + +template +inline ReturnValue_t FIFOBase::pop() { + T value; + return this->retrieve(&value); +}; + +template +inline bool FIFOBase::empty() { + return (currentSize == 0); +}; + +template +inline bool FIFOBase::full() { + return (currentSize == maxCapacity); +} + +template +inline size_t FIFOBase::size() { + return currentSize; +} + +template +inline size_t FIFOBase::next(size_t current) { + ++current; + if (current == maxCapacity) { + current = 0; + } + return current; +} + +#endif diff --git a/container/StaticFIFO.h b/container/StaticFIFO.h new file mode 100644 index 00000000..651c4989 --- /dev/null +++ b/container/StaticFIFO.h @@ -0,0 +1,23 @@ +#ifndef FRAMEWORK_CONTAINER_STATICFIFO_H_ +#define FRAMEWORK_CONTAINER_STATICFIFO_H_ + +#include +#include + +/** + * @brief Simple First-In-First-Out data structure with size fixed at + * compile time. The public interface of FIFOBase exposes + * the user interface for the FIFO. + * @tparam T Entry Type + * @tparam capacity Maximum capacity + */ +template +class StaticFIFO: public FIFOBase { +public: + StaticFIFO(): FIFOBase(values.data(), capacity) {}; + +private: + std::array values; +}; + +#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ From 991385de6576583e4a45aa8c059c23f964094434 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Jul 2020 13:29:56 +0200 Subject: [PATCH 02/20] added missing include, CSB uses static fifo now --- container/StaticFIFO.h | 1 + tmtcservices/CommandingServiceBase.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/container/StaticFIFO.h b/container/StaticFIFO.h index 651c4989..780b0383 100644 --- a/container/StaticFIFO.h +++ b/container/StaticFIFO.h @@ -3,6 +3,7 @@ #include #include +#include /** * @brief Simple First-In-First-Out data structure with size fixed at diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index bf2e8242..b3132be5 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -2,7 +2,7 @@ #define COMMANDINGSERVICEBASE_H_ #include -#include +#include #include #include #include @@ -179,7 +179,7 @@ protected: uint32_t state; Command_t command; object_id_t objectId; - FIFO fifo; + StaticFIFO fifo; }; const uint16_t apid; From b699c8b2b3be6446502c107f893c8b53201f5bc9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Jul 2020 13:38:11 +0200 Subject: [PATCH 03/20] put FIFO in namespace, fixed doc --- container/FIFO.h | 4 ++++ container/FIFOBase.h | 8 ++++++-- container/StaticFIFO.h | 10 ++++++++-- tmtcservices/CommandingServiceBase.h | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/container/FIFO.h b/container/FIFO.h index 217ddbca..801df6a2 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -4,6 +4,8 @@ #include #include +namespace fifo { + /** * @brief Simple First-In-First-Out data structure. The maximum size * can be set in the constructor. THe public interface of @@ -23,4 +25,6 @@ private: std::vector values; }; +} + #endif /* FRAMEWORK_CONTAINER_FIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h index c6a74d2f..ac5c6e2c 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -4,6 +4,8 @@ #include #include +namespace fsfw { + template class FIFOBase { public: @@ -11,8 +13,8 @@ public: static const ReturnValue_t FULL = MAKE_RETURN_CODE(1); static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2); - - /** Default ctor, no input arguments required. */ + /** Default ctor, takes pointer to first entry of underlying container + * and maximum capacity */ FIFOBase(T* values, const size_t maxCapacity); /** @@ -56,4 +58,6 @@ private: #include +} + #endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */ diff --git a/container/StaticFIFO.h b/container/StaticFIFO.h index 780b0383..f3128200 100644 --- a/container/StaticFIFO.h +++ b/container/StaticFIFO.h @@ -5,10 +5,14 @@ #include #include +namespace fsfw { + /** * @brief Simple First-In-First-Out data structure with size fixed at - * compile time. The public interface of FIFOBase exposes - * the user interface for the FIFO. + * compile time + * @details + * Performs no dynamic memory allocation. + * The public interface of FIFOBase exposes the user interface for the FIFO. * @tparam T Entry Type * @tparam capacity Maximum capacity */ @@ -21,4 +25,6 @@ private: std::array values; }; +} + #endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index b3132be5..a4343065 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -179,7 +179,7 @@ protected: uint32_t state; Command_t command; object_id_t objectId; - StaticFIFO fifo; + fsfw::StaticFIFO fifo; }; const uint16_t apid; From 8f6c3b50af92e9e5619a79e48414a8e252e29577 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Jul 2020 13:40:13 +0200 Subject: [PATCH 04/20] namespace fix --- container/FIFO.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/container/FIFO.h b/container/FIFO.h index 801df6a2..7251321f 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -4,12 +4,15 @@ #include #include -namespace fifo { +namespace fsfw { /** * @brief Simple First-In-First-Out data structure. The maximum size - * can be set in the constructor. THe public interface of - * FIFOBase exposes the user interface for the FIFO. + * can be set in the constructor. + * @details + * The maximum capacity can be determined at run-time, so this container + * performs dynamic memory allocation! + * The public interface of FIFOBase exposes the user interface for the FIFO. * @tparam T Entry Type * @tparam capacity Maximum capacity */ From 2fccc4fef77537a62f39297f1c5bf39fbc9ea08f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Jul 2020 23:08:31 +0200 Subject: [PATCH 05/20] getter function for capacity --- container/FIFO.h | 6 ++---- container/FIFOBase.h | 4 +++- container/FIFOBase.tpp | 5 +++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/container/FIFO.h b/container/FIFO.h index 7251321f..19daaf1b 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -19,10 +19,8 @@ namespace fsfw { template class FIFO: public FIFOBase { public: - FIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity) { - values.reserve(maxCapacity); - values.resize(maxCapacity); - }; + FIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity), + values(maxCapacity) {}; private: std::vector values; diff --git a/container/FIFOBase.h b/container/FIFOBase.h index ac5c6e2c..6ed7d924 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -45,9 +45,11 @@ public: bool full(); size_t size(); + size_t getMaxCapacity() const; + private: T* values; - size_t maxCapacity; + size_t maxCapacity = 0; size_t readIndex = 0; size_t writeIndex = 0; diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp index 011ce6de..48a060ff 100644 --- a/container/FIFOBase.tpp +++ b/container/FIFOBase.tpp @@ -73,4 +73,9 @@ inline size_t FIFOBase::next(size_t current) { return current; } +template +inline size_t FIFOBase::getMaxCapacity() const { + return maxCapacity; +} + #endif From 5f76b03f3ab29b5f401124ad2a0a137a6828d285 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 7 Jul 2020 17:44:15 +0200 Subject: [PATCH 06/20] fifo tweaks --- container/DynamicFIFO.h | 27 +++++++++++++++++++++++++++ container/FIFO.h | 23 +++++++++-------------- container/FIFOBase.h | 4 ---- container/StaticFIFO.h | 30 ------------------------------ 4 files changed, 36 insertions(+), 48 deletions(-) create mode 100644 container/DynamicFIFO.h delete mode 100644 container/StaticFIFO.h diff --git a/container/DynamicFIFO.h b/container/DynamicFIFO.h new file mode 100644 index 00000000..3a5242c7 --- /dev/null +++ b/container/DynamicFIFO.h @@ -0,0 +1,27 @@ +#ifndef FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ +#define FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ + +#include +#include + +/** + * @brief Simple First-In-First-Out data structure. The maximum size + * can be set in the constructor. + * @details + * The maximum capacity can be determined at run-time, so this container + * performs dynamic memory allocation! + * The public interface of FIFOBase exposes the user interface for the FIFO. + * @tparam T Entry Type + * @tparam capacity Maximum capacity + */ +template +class DynamicFIFO: public FIFOBase { +public: + DynamicFIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity), + values(maxCapacity) {}; + +private: + std::vector values; +}; + +#endif /* FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ */ diff --git a/container/FIFO.h b/container/FIFO.h index 19daaf1b..ecb218fd 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -1,31 +1,26 @@ #ifndef FRAMEWORK_CONTAINER_FIFO_H_ #define FRAMEWORK_CONTAINER_FIFO_H_ +#include #include -#include - -namespace fsfw { +#include /** - * @brief Simple First-In-First-Out data structure. The maximum size - * can be set in the constructor. + * @brief Simple First-In-First-Out data structure with size fixed at + * compile time * @details - * The maximum capacity can be determined at run-time, so this container - * performs dynamic memory allocation! + * Performs no dynamic memory allocation. * The public interface of FIFOBase exposes the user interface for the FIFO. * @tparam T Entry Type * @tparam capacity Maximum capacity */ -template +template class FIFO: public FIFOBase { public: - FIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity), - values(maxCapacity) {}; + FIFO(): FIFOBase(values.data(), capacity) {}; private: - std::vector values; + std::array values; }; -} - -#endif /* FRAMEWORK_CONTAINER_FIFO_H_ */ +#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h index 6ed7d924..8bdb333f 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -4,8 +4,6 @@ #include #include -namespace fsfw { - template class FIFOBase { public: @@ -60,6 +58,4 @@ private: #include -} - #endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */ diff --git a/container/StaticFIFO.h b/container/StaticFIFO.h deleted file mode 100644 index f3128200..00000000 --- a/container/StaticFIFO.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef FRAMEWORK_CONTAINER_STATICFIFO_H_ -#define FRAMEWORK_CONTAINER_STATICFIFO_H_ - -#include -#include -#include - -namespace fsfw { - -/** - * @brief Simple First-In-First-Out data structure with size fixed at - * compile time - * @details - * Performs no dynamic memory allocation. - * The public interface of FIFOBase exposes the user interface for the FIFO. - * @tparam T Entry Type - * @tparam capacity Maximum capacity - */ -template -class StaticFIFO: public FIFOBase { -public: - StaticFIFO(): FIFOBase(values.data(), capacity) {}; - -private: - std::array values; -}; - -} - -#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ From d795892d578772cc04ac159a228f9501ab39d8db Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 7 Jul 2020 17:54:09 +0200 Subject: [PATCH 07/20] csb fifo tweak --- tmtcservices/CommandingServiceBase.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index a4343065..e7702860 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -1,8 +1,8 @@ -#ifndef COMMANDINGSERVICEBASE_H_ -#define COMMANDINGSERVICEBASE_H_ +#ifndef FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ +#define FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ #include -#include +#include #include #include #include @@ -179,7 +179,7 @@ protected: uint32_t state; Command_t command; object_id_t objectId; - fsfw::StaticFIFO fifo; + FIFO fifo; }; const uint16_t apid; @@ -286,4 +286,4 @@ private: void checkTimeout(); }; -#endif /* COMMANDINGSERVICEBASE_H_ */ +#endif /* FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ */ From 65d71b1c65b2841a94d0fa1cb95b849afa2cff47 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 7 Jul 2020 18:11:36 +0200 Subject: [PATCH 08/20] added new ctor, non-allocating --- container/SimpleRingBuffer.cpp | 18 +++++++---- container/SimpleRingBuffer.h | 57 +++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/container/SimpleRingBuffer.cpp b/container/SimpleRingBuffer.cpp index 63dc3514..731c9dc9 100644 --- a/container/SimpleRingBuffer.cpp +++ b/container/SimpleRingBuffer.cpp @@ -1,18 +1,23 @@ #include -#include +#include -SimpleRingBuffer::SimpleRingBuffer(uint32_t size, bool overwriteOld) : - RingBufferBase<>(0, size, overwriteOld), buffer(NULL) { +SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld) : + RingBufferBase<>(0, size, overwriteOld) { buffer = new uint8_t[size]; } +SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size, + bool overwriteOld): + RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {} + + SimpleRingBuffer::~SimpleRingBuffer() { delete[] buffer; } ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, uint32_t amount) { - if (availableWriteSpace() >= amount || overwriteOld) { + if (availableWriteSpace() >= amount or overwriteOld) { uint32_t amountTillWrap = writeTillWrap(); if (amountTillWrap >= amount) { memcpy(&buffer[write], data, amount); @@ -38,7 +43,7 @@ ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, uint32_t amount, return HasReturnvaluesIF::RETURN_FAILED; } } - if (trueAmount != NULL) { + if (trueAmount != nullptr) { *trueAmount = amount; } if (amountTillWrap >= amount) { @@ -60,9 +65,10 @@ ReturnValue_t SimpleRingBuffer::deleteData(uint32_t amount, return HasReturnvaluesIF::RETURN_FAILED; } } - if (trueAmount != NULL) { + if (trueAmount != nullptr) { *trueAmount = amount; } incrementRead(amount, READ_PTR); return HasReturnvaluesIF::RETURN_OK; } + diff --git a/container/SimpleRingBuffer.h b/container/SimpleRingBuffer.h index 6d7d67e1..30dd184c 100644 --- a/container/SimpleRingBuffer.h +++ b/container/SimpleRingBuffer.h @@ -2,19 +2,66 @@ #define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ #include -#include +#include +/** + * @brief Circular buffer implementation, useful for buffering + * into data streams. + * @details + * Note that the deleteData() has to be called to increment the read pointer. + * This class allocated dynamically, so + * @ingroup containers + */ class SimpleRingBuffer: public RingBufferBase<> { public: - SimpleRingBuffer(uint32_t size, bool overwriteOld); + /** + * This constructor allocates a new internal buffer with the supplied size. + * @param size + * @param overwriteOld + */ + SimpleRingBuffer(const size_t size, bool overwriteOld); + /** + * This constructor takes an external buffer with the specified size. + * @param buffer + * @param size + * @param overwriteOld + */ + SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld); + virtual ~SimpleRingBuffer(); + + /** + * Write to circular buffer and increment write pointer by amount + * @param data + * @param amount + * @return + */ ReturnValue_t writeData(const uint8_t* data, uint32_t amount); - ReturnValue_t readData(uint8_t* data, uint32_t amount, bool readRemaining = false, uint32_t* trueAmount = NULL); - ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, uint32_t* trueAmount = NULL); + + /** + * Read from circular buffer at read pointer + * @param data + * @param amount + * @param readRemaining + * @param trueAmount + * @return + */ + ReturnValue_t readData(uint8_t* data, uint32_t amount, + bool readRemaining = false, uint32_t* trueAmount = nullptr); + + /** + * Delete data starting by incrementing read pointer + * @param amount + * @param deleteRemaining + * @param trueAmount + * @return + */ + ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, + uint32_t* trueAmount = nullptr); private: // static const uint8_t TEMP_READ_PTR = 1; static const uint8_t READ_PTR = 0; - uint8_t* buffer; + uint8_t* buffer = nullptr; }; #endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ From 3a2dc5eeb60d3b06d3e77a29b433482cb53f94f0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 13 Jul 2020 13:33:12 +0200 Subject: [PATCH 09/20] new tmtc unix udp bridge --- osal/linux/TcUnixUdpPollingTask.cpp | 137 +++++++++++++++++++++++ osal/linux/TcUnixUdpPollingTask.h | 67 +++++++++++ osal/linux/TmTcUnixUdpBridge.cpp | 168 ++++++++++++++++++++++++++++ osal/linux/TmTcUnixUdpBridge.h | 48 ++++++++ 4 files changed, 420 insertions(+) create mode 100644 osal/linux/TcUnixUdpPollingTask.cpp create mode 100644 osal/linux/TcUnixUdpPollingTask.h create mode 100644 osal/linux/TmTcUnixUdpBridge.cpp create mode 100644 osal/linux/TmTcUnixUdpBridge.h diff --git a/osal/linux/TcUnixUdpPollingTask.cpp b/osal/linux/TcUnixUdpPollingTask.cpp new file mode 100644 index 00000000..8cf7b285 --- /dev/null +++ b/osal/linux/TcUnixUdpPollingTask.cpp @@ -0,0 +1,137 @@ +#include +#include + +TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId, + object_id_t tmtcUnixUdpBridge, size_t frameSize, + double timeoutSeconds): SystemObject(objectId), + tmtcBridgeId(tmtcUnixUdpBridge) { + + if(frameSize > 0) { + this->frameSize = frameSize; + } + else { + this->frameSize = DEFAULT_MAX_FRAME_SIZE; + } + + // Set up reception buffer with specified frame size. + // For now, it is assumed that only one frame is held in the buffer! + receptionBuffer.reserve(this->frameSize); + receptionBuffer.resize(this->frameSize); + + if(timeoutSeconds == -1) { + receptionTimeout = DEFAULT_TIMEOUT; + } + else { + receptionTimeout = timevalOperations::toTimeval(timeoutSeconds); + } +} + +TcUnixUdpPollingTask::~TcUnixUdpPollingTask() {} + +ReturnValue_t TcUnixUdpPollingTask::performOperation(uint8_t opCode) { + // Poll for new UDP datagrams in permanent loop. + while(1) { + //! Sender Address is cached here. + struct sockaddr_in senderAddress; + socklen_t senderSockLen = 0; + ssize_t bytesReceived = recvfrom(serverUdpSocket, + receptionBuffer.data(), frameSize, receptionFlags, + reinterpret_cast(&senderAddress), &senderSockLen); + if(bytesReceived < 0) { + // handle error + sif::error << "TcSocketPollingTask::performOperation: Reception" + "error." << std::endl; + handleReadError(); + + continue; + } +// sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived +// << " bytes received" << std::endl; + + ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); + if(result != HasReturnvaluesIF::RETURN_FAILED) { + + } + tmtcBridge->registerCommConnect(); + tmtcBridge->checkAndSetClientAddress(senderAddress); + } + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t TcUnixUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) { + store_address_t storeId; + ReturnValue_t result = tcStore->addData(&storeId, + receptionBuffer.data(), bytesRead); + // arrayprinter::print(receptionBuffer.data(), bytesRead); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "TcSerialPollingTask::transferPusToSoftwareBus: Data " + "storage failed" << std::endl; + sif::error << "Packet size: " << bytesRead << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + TmTcMessage message(storeId); + + result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "Serial Polling: Sending message to queue failed" + << std::endl; + tcStore->deleteData(storeId); + } + return result; +} + +ReturnValue_t TcUnixUdpPollingTask::initialize() { + tcStore = objectManager->get(objects::TC_STORE); + if (tcStore == nullptr) { + sif::error << "TcSerialPollingTask::initialize: TC Store uninitialized!" + << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + tmtcBridge = objectManager->get(tmtcBridgeId); + if(tmtcBridge == nullptr) { + sif::error << "TcSocketPollingTask::TcSocketPollingTask: Invalid" + " TMTC bridge object!" << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + serverUdpSocket = tmtcBridge->serverSocket; + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t TcUnixUdpPollingTask::initializeAfterTaskCreation() { + // Initialize the destination after task creation. This ensures + // that the destination will be set in the TMTC bridge. + targetTcDestination = tmtcBridge->getRequestQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + +void TcUnixUdpPollingTask::setTimeout(double timeoutSeconds) { + timeval tval; + tval = timevalOperations::toTimeval(timeoutSeconds); + int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO, + &tval, sizeof(receptionTimeout)); + if(result == -1) { + sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting " + "receive timeout failed with " << strerror(errno) << std::endl; + } +} + +void TcUnixUdpPollingTask::handleReadError() { + switch(errno) { + case(EAGAIN): { + // todo: When working in timeout mode, this will occur more often + // and is not an error. + sif::error << "TcUnixUdpPollingTask::handleReadError: Timeout." + << std::endl; + break; + } + default: { + sif::error << "TcUnixUdpPollingTask::handleReadError: " + << strerror(errno) << std::endl; + } + } +} diff --git a/osal/linux/TcUnixUdpPollingTask.h b/osal/linux/TcUnixUdpPollingTask.h new file mode 100644 index 00000000..d8de1458 --- /dev/null +++ b/osal/linux/TcUnixUdpPollingTask.h @@ -0,0 +1,67 @@ +#ifndef FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ +#define FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ + +#include +#include +#include + +#include +#include + +/** + * @brief This class can be used to implement the polling of a Unix socket, + * using UDP for now. + * @details + * The task will be blocked while the specified number of bytes has not been + * received, so TC reception is handled inside a separate task. + * This class caches the IP address of the sender. It is assumed there + * is only one sender for now. + */ +class TcUnixUdpPollingTask: public SystemObject, + public ExecutableObjectIF { + friend class TmTcUnixUdpBridge; +public: + static constexpr size_t DEFAULT_MAX_FRAME_SIZE = 2048; + //! 0.5 default milliseconds timeout for now. + static constexpr timeval DEFAULT_TIMEOUT = {.tv_sec = 0, .tv_usec = 500}; + + TcUnixUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, + size_t frameSize = 0, double timeoutSeconds = -1); + virtual~ TcUnixUdpPollingTask(); + + /** + * Turn on optional timeout for UDP polling. In the default mode, + * the receive function will block until a packet is received. + * @param timeoutSeconds + */ + void setTimeout(double timeoutSeconds); + + virtual ReturnValue_t performOperation(uint8_t opCode) override; + virtual ReturnValue_t initialize() override; + virtual ReturnValue_t initializeAfterTaskCreation() override; + +protected: + StorageManagerIF* tcStore = nullptr; + +private: + //! TMTC bridge is cached. + object_id_t tmtcBridgeId = objects::NO_OBJECT; + TmTcUnixUdpBridge* tmtcBridge = nullptr; + MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; + //! Reception flags: https://linux.die.net/man/2/recvfrom. + int receptionFlags = 0; + + //! Server socket, which is member of TMTC bridge and is assigned in + //! constructor + int serverUdpSocket = 0; + + std::vector receptionBuffer; + + size_t frameSize = 0; + timeval receptionTimeout; + + ReturnValue_t handleSuccessfullTcRead(size_t bytesRead); + void handleReadError(); +}; + +#endif /* FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ */ diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp new file mode 100644 index 00000000..92fbbdfa --- /dev/null +++ b/osal/linux/TmTcUnixUdpBridge.cpp @@ -0,0 +1,168 @@ +#include +#include +#include + +#include +#include + +TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, + object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId, + uint16_t serverPort, uint16_t clientPort): + TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { + mutex = MutexFactory::instance()->createMutex(); + + uint16_t setServerPort = DEFAULT_UDP_SERVER_PORT; + if(serverPort != 0xFFFF) { + setServerPort = serverPort; + } + + uint16_t setClientPort = DEFAULT_UDP_CLIENT_PORT; + if(clientPort != 0xFFFF) { + setClientPort = clientPort; + } + + // Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html + //clientSocket = socket(AF_INET, SOCK_DGRAM, 0); + serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(socket < 0) { + sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open" + " UDP socket!" << std::endl; + handleSocketError(); + return; + } + + serverAddress.sin_family = AF_INET; + + // Accept packets from any interface. + //serverAddress.sin_addr.s_addr = inet_addr("127.73.73.0"); + serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); + serverAddress.sin_port = htons(setServerPort); + serverAddressLen = sizeof(serverAddress); + setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &serverSocketOptions, + sizeof(serverSocketOptions)); + + clientAddress.sin_family = AF_INET; + clientAddress.sin_addr.s_addr = htonl(INADDR_ANY); + clientAddress.sin_port = htons(setClientPort); + clientAddressLen = sizeof(clientAddress); + + int result = bind(serverSocket, + reinterpret_cast(&serverAddress), + serverAddressLen); + if(result == -1) { + sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not bind " + "local port " << setServerPort << " to server socket!" + << std::endl; + handleBindError(); + return; + } +} + +TmTcUnixUdpBridge::~TmTcUnixUdpBridge() { +} + +ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { + int flags = 0; + + clientAddress.sin_addr.s_addr = htons(INADDR_ANY); + //clientAddress.sin_addr.s_addr = inet_addr("127.73.73.1"); + clientAddressLen = sizeof(serverAddress); + +// char ipAddress [15]; +// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, +// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; + + ssize_t bytesSent = sendto(serverSocket, data, dataLen, flags, + reinterpret_cast(&clientAddress), clientAddressLen); + if(bytesSent < 0) { + sif::error << "TmTcUnixUdpBridge::sendTm: Send operation failed." + << std::endl; + handleSendError(); + } +// sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were" +// " sent." << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) { + MutexHelper lock(mutex, 10); + +// char ipAddress [15]; +// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, +// &newAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; +// sif::debug << "IP Address Old: " << inet_ntop(AF_INET, +// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; + + // Set new IP address if it has changed. + if(clientAddress.sin_addr.s_addr != newAddress.sin_addr.s_addr) { + clientAddress.sin_addr.s_addr = newAddress.sin_addr.s_addr; + clientAddressLen = sizeof(clientAddress); + } +} + +void TmTcUnixUdpBridge::handleSocketError() { + + // See: https://man7.org/linux/man-pages/man2/socket.2.html + switch(errno) { + case(EACCES): + case(EINVAL): + case(EMFILE): + case(ENFILE): + case(EAFNOSUPPORT): + case(ENOBUFS): + case(ENOMEM): + case(EPROTONOSUPPORT): + sif::error << "TmTcUnixBridge::handleSocketError: Socket creation failed" + << " with " << strerror(errno) << std::endl; + break; + default: + sif::error << "TmTcUnixBridge::handleSocketError: Unknown error" + << std::endl; + break; + } +} + +void TmTcUnixUdpBridge::handleBindError() { + // See: https://man7.org/linux/man-pages/man2/bind.2.html + switch(errno) { + case(EACCES): { + /* + Ephermeral ports can be shown with following command: + sysctl -A | grep ip_local_port_range + */ + sif::error << "TmTcUnixBridge::handleBindError: Port access issue." + "Ports 1-1024 are reserved on UNIX systems and require root " + "rights while ephermeral ports should not be used as well." + << std::endl; + } + break; + case(EADDRINUSE): + case(EBADF): + case(EINVAL): + case(ENOTSOCK): + case(EADDRNOTAVAIL): + case(EFAULT): + case(ELOOP): + case(ENAMETOOLONG): + case(ENOENT): + case(ENOMEM): + case(ENOTDIR): + case(EROFS): { + sif::error << "TmTcUnixBridge::handleBindError: Socket creation failed" + << " with " << strerror(errno) << std::endl; + break; + } + default: + sif::error << "TmTcUnixBridge::handleBindError: Unknown error" + << std::endl; + break; + } +} + +void TmTcUnixUdpBridge::handleSendError() { + switch(errno) { + default: + sif::error << "Error: " << strerror(errno) << std::endl; + } +} + diff --git a/osal/linux/TmTcUnixUdpBridge.h b/osal/linux/TmTcUnixUdpBridge.h new file mode 100644 index 00000000..dbddc6c3 --- /dev/null +++ b/osal/linux/TmTcUnixUdpBridge.h @@ -0,0 +1,48 @@ +#ifndef FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ +#define FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ + +#include +#include +#include +#include +#include + +class TmTcUnixUdpBridge: public TmTcBridge { + friend class TcUnixUdpPollingTask; +public: + // The ports chosen here should not be used by any other process. + // List of used ports on Linux: /etc/services + static constexpr uint16_t DEFAULT_UDP_SERVER_PORT = 7301; + static constexpr uint16_t DEFAULT_UDP_CLIENT_PORT = 7302; + + TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination, + object_id_t tmStoreId, object_id_t tcStoreId, + uint16_t serverPort = 0xFFFF,uint16_t clientPort = 0xFFFF); + virtual~ TmTcUnixUdpBridge(); + + void checkAndSetClientAddress(sockaddr_in clientAddress); + +protected: + virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override; + +private: + int serverSocket = 0; + + const int serverSocketOptions = 0; + + struct sockaddr_in clientAddress; + socklen_t clientAddressLen = 0; + + struct sockaddr_in serverAddress; + socklen_t serverAddressLen = 0; + + //! Access to the client address is mutex protected as it is set + //! by another task. + MutexIF* mutex; + + void handleSocketError(); + void handleBindError(); + void handleSendError(); +}; + +#endif /* FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ */ From 0449c63225de411920dba5a3b7bb88a9eb6c72d1 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 28 Jul 2020 13:13:40 +0200 Subject: [PATCH 10/20] bugfixes --- container/DynamicFIFO.h | 21 ++++++++++++++++++--- container/FIFO.h | 12 ++++++++++-- container/FIFOBase.h | 8 ++++++-- container/FIFOBase.tpp | 8 +++++++- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/container/DynamicFIFO.h b/container/DynamicFIFO.h index 3a5242c7..59adfb3a 100644 --- a/container/DynamicFIFO.h +++ b/container/DynamicFIFO.h @@ -17,11 +17,26 @@ template class DynamicFIFO: public FIFOBase { public: - DynamicFIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity), - values(maxCapacity) {}; + DynamicFIFO(size_t maxCapacity): FIFOBase(nullptr, maxCapacity), + fifoVector(maxCapacity) { + // trying to pass the pointer of the uninitialized vector + // to the FIFOBase constructor directly lead to a super evil bug. + // So we do it like this now. + this->setData(fifoVector.data()); + }; + + /** + * @brief Custom copy constructor which prevents setting the + * underlying pointer wrong. + */ + DynamicFIFO(const DynamicFIFO& other): FIFOBase(other), + fifoVector(other.maxCapacity) { + this->setData(fifoVector.data()); + } + private: - std::vector values; + std::vector fifoVector; }; #endif /* FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ */ diff --git a/container/FIFO.h b/container/FIFO.h index ecb218fd..2e332dc2 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -17,10 +17,18 @@ template class FIFO: public FIFOBase { public: - FIFO(): FIFOBase(values.data(), capacity) {}; + FIFO(): FIFOBase(fifoArray.data(), capacity) {}; + + /** + * @brief Custom copy constructor to set pointer correctly. + * @param other + */ + FIFO(const FIFO& other): FIFOBase(other) { + this->setData(fifoArray.data()); + } private: - std::array values; + std::array fifoArray; }; #endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h index 8bdb333f..7f8bde96 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -3,6 +3,7 @@ #include #include +#include template class FIFOBase { @@ -43,12 +44,15 @@ public: bool full(); size_t size(); + size_t getMaxCapacity() const; -private: - T* values; +protected: + void setData(T* data); size_t maxCapacity = 0; + T* values; + size_t readIndex = 0; size_t writeIndex = 0; size_t currentSize = 0; diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp index 48a060ff..c73e9d59 100644 --- a/container/FIFOBase.tpp +++ b/container/FIFOBase.tpp @@ -7,7 +7,7 @@ template inline FIFOBase::FIFOBase(T* values, const size_t maxCapacity): - values(values), maxCapacity(maxCapacity) {}; + maxCapacity(maxCapacity), values(values){}; template inline ReturnValue_t FIFOBase::insert(T value) { @@ -78,4 +78,10 @@ inline size_t FIFOBase::getMaxCapacity() const { return maxCapacity; } + +template +inline void FIFOBase::setData(T *data) { + this->values = data; +} + #endif From eb503ae030fdc5a8c7925f58cad85427d77251cf Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 20:19:27 +0200 Subject: [PATCH 11/20] include guard fix --- container/DynamicFIFO.h | 6 +++--- container/FIFOBase.h | 6 +++--- container/FIFOBase.tpp | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/container/DynamicFIFO.h b/container/DynamicFIFO.h index 5cdae81a..7fa0c32c 100644 --- a/container/DynamicFIFO.h +++ b/container/DynamicFIFO.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ -#define FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ +#ifndef FSFW_CONTAINER_DYNAMICFIFO_H_ +#define FSFW_CONTAINER_DYNAMICFIFO_H_ #include "FIFOBase.h" #include @@ -39,4 +39,4 @@ private: std::vector fifoVector; }; -#endif /* FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ */ +#endif /* FSFW_CONTAINER_DYNAMICFIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h index acb38b82..bbabd67c 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_ -#define FRAMEWORK_CONTAINER_FIFOBASE_H_ +#ifndef FSFW_CONTAINER_FIFOBASE_H_ +#define FSFW_CONTAINER_FIFOBASE_H_ #include "../returnvalues/HasReturnvaluesIF.h" #include @@ -62,4 +62,4 @@ protected: #include "FIFOBase.tpp" -#endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */ +#endif /* FSFW_CONTAINER_FIFOBASE_H_ */ diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp index c73e9d59..e1287dcf 100644 --- a/container/FIFOBase.tpp +++ b/container/FIFOBase.tpp @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_CONTAINER_FIFOBASE_TPP_ -#define FRAMEWORK_CONTAINER_FIFOBASE_TPP_ +#ifndef FSFW_CONTAINER_FIFOBASE_TPP_ +#define FSFW_CONTAINER_FIFOBASE_TPP_ -#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_ +#ifndef FSFW_CONTAINER_FIFOBASE_H_ #error Include FIFOBase.h before FIFOBase.tpp! #endif From aec557a8c06a233b3139134a8fa5db0befb4e757 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 28 Aug 2020 17:14:20 +0200 Subject: [PATCH 12/20] updated unix udp bridge --- globalfunctions/timevalOperations.cpp | 191 +++++++++++++------------- globalfunctions/timevalOperations.h | 1 + osal/linux/TcUnixUdpPollingTask.cpp | 4 +- osal/linux/TcUnixUdpPollingTask.h | 6 +- osal/linux/TmTcUnixUdpBridge.cpp | 8 +- osal/linux/TmTcUnixUdpBridge.h | 4 +- 6 files changed, 111 insertions(+), 103 deletions(-) diff --git a/globalfunctions/timevalOperations.cpp b/globalfunctions/timevalOperations.cpp index 6efe75ba..ae49ef21 100644 --- a/globalfunctions/timevalOperations.cpp +++ b/globalfunctions/timevalOperations.cpp @@ -1,92 +1,99 @@ -#include "timevalOperations.h" - -timeval& operator+=(timeval& lhs, const timeval& rhs) { - int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; - sum += rhs.tv_sec * 1000000. + rhs.tv_usec; - lhs.tv_sec = sum / 1000000; - lhs.tv_usec = sum - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator+(timeval lhs, const timeval& rhs) { - lhs += rhs; - return lhs; -} - -timeval& operator-=(timeval& lhs, const timeval& rhs) { - int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; - sum -= rhs.tv_sec * 1000000. + rhs.tv_usec; - lhs.tv_sec = sum / 1000000; - lhs.tv_usec = sum - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator-(timeval lhs, const timeval& rhs) { - lhs -= rhs; - return lhs; -} - -double operator/(const timeval& lhs, const timeval& rhs) { - double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 / rhs64; -} - -timeval& operator/=(timeval& lhs, double scalar) { - int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; - product /= scalar; - lhs.tv_sec = product / 1000000; - lhs.tv_usec = product - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator/(timeval lhs, double scalar) { - lhs /= scalar; - return lhs; -} - -timeval& operator*=(timeval& lhs, double scalar) { - int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; - product *= scalar; - lhs.tv_sec = product / 1000000; - lhs.tv_usec = product - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator*(timeval lhs, double scalar) { - lhs *= scalar; - return lhs; -} - -timeval operator*(double scalar, timeval rhs) { - rhs *= scalar; - return rhs; -} - -bool operator==(const timeval& lhs, const timeval& rhs) { - int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 == rhs64; -} -bool operator!=(const timeval& lhs, const timeval& rhs) { - return !operator==(lhs, rhs); -} -bool operator<(const timeval& lhs, const timeval& rhs) { - int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 < rhs64; -} -bool operator>(const timeval& lhs, const timeval& rhs) { - return operator<(rhs, lhs); -} -bool operator<=(const timeval& lhs, const timeval& rhs) { - return !operator>(lhs, rhs); -} -bool operator>=(const timeval& lhs, const timeval& rhs) { - return !operator<(lhs, rhs); -} - -double timevalOperations::toDouble(const timeval timeval) { - double result = timeval.tv_sec * 1000000. + timeval.tv_usec; - return result / 1000000.; -} +#include "timevalOperations.h" + +timeval& operator+=(timeval& lhs, const timeval& rhs) { + int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; + sum += rhs.tv_sec * 1000000. + rhs.tv_usec; + lhs.tv_sec = sum / 1000000; + lhs.tv_usec = sum - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator+(timeval lhs, const timeval& rhs) { + lhs += rhs; + return lhs; +} + +timeval& operator-=(timeval& lhs, const timeval& rhs) { + int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; + sum -= rhs.tv_sec * 1000000. + rhs.tv_usec; + lhs.tv_sec = sum / 1000000; + lhs.tv_usec = sum - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator-(timeval lhs, const timeval& rhs) { + lhs -= rhs; + return lhs; +} + +double operator/(const timeval& lhs, const timeval& rhs) { + double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 / rhs64; +} + +timeval& operator/=(timeval& lhs, double scalar) { + int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; + product /= scalar; + lhs.tv_sec = product / 1000000; + lhs.tv_usec = product - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator/(timeval lhs, double scalar) { + lhs /= scalar; + return lhs; +} + +timeval& operator*=(timeval& lhs, double scalar) { + int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; + product *= scalar; + lhs.tv_sec = product / 1000000; + lhs.tv_usec = product - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator*(timeval lhs, double scalar) { + lhs *= scalar; + return lhs; +} + +timeval operator*(double scalar, timeval rhs) { + rhs *= scalar; + return rhs; +} + +bool operator==(const timeval& lhs, const timeval& rhs) { + int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 == rhs64; +} +bool operator!=(const timeval& lhs, const timeval& rhs) { + return !operator==(lhs, rhs); +} +bool operator<(const timeval& lhs, const timeval& rhs) { + int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 < rhs64; +} +bool operator>(const timeval& lhs, const timeval& rhs) { + return operator<(rhs, lhs); +} +bool operator<=(const timeval& lhs, const timeval& rhs) { + return !operator>(lhs, rhs); +} +bool operator>=(const timeval& lhs, const timeval& rhs) { + return !operator<(lhs, rhs); +} + +double timevalOperations::toDouble(const timeval timeval) { + double result = timeval.tv_sec * 1000000. + timeval.tv_usec; + return result / 1000000.; +} + +timeval timevalOperations::toTimeval(const double seconds) { + timeval tval; + tval.tv_sec = seconds; + tval.tv_usec = seconds *(double) 1e6 - (tval.tv_sec *1e6); + return tval; +} diff --git a/globalfunctions/timevalOperations.h b/globalfunctions/timevalOperations.h index a553e60a..3977d5d9 100644 --- a/globalfunctions/timevalOperations.h +++ b/globalfunctions/timevalOperations.h @@ -41,6 +41,7 @@ namespace timevalOperations { * @return seconds */ double toDouble(const timeval timeval); +timeval toTimeval(const double seconds); } #endif /* TIMEVALOPERATIONS_H_ */ diff --git a/osal/linux/TcUnixUdpPollingTask.cpp b/osal/linux/TcUnixUdpPollingTask.cpp index 8cf7b285..95910b02 100644 --- a/osal/linux/TcUnixUdpPollingTask.cpp +++ b/osal/linux/TcUnixUdpPollingTask.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "TcUnixUdpPollingTask.h" +#include "../../globalfunctions/arrayprinter.h" TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, size_t frameSize, diff --git a/osal/linux/TcUnixUdpPollingTask.h b/osal/linux/TcUnixUdpPollingTask.h index d8de1458..cc032561 100644 --- a/osal/linux/TcUnixUdpPollingTask.h +++ b/osal/linux/TcUnixUdpPollingTask.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ #define FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ -#include -#include -#include +#include "../../objectmanager/SystemObject.h" +#include "../../osal/linux/TmTcUnixUdpBridge.h" +#include "../../tasks/ExecutableObjectIF.h" #include #include diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp index 92fbbdfa..46b26254 100644 --- a/osal/linux/TmTcUnixUdpBridge.cpp +++ b/osal/linux/TmTcUnixUdpBridge.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "TmTcUnixUdpBridge.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../ipc/MutexHelper.h" #include #include @@ -85,7 +85,7 @@ ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { } void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) { - MutexHelper lock(mutex, 10); + MutexHelper lock(mutex, MutexIF::TimeoutType::WAITING, 10); // char ipAddress [15]; // sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, diff --git a/osal/linux/TmTcUnixUdpBridge.h b/osal/linux/TmTcUnixUdpBridge.h index dbddc6c3..5245c44c 100644 --- a/osal/linux/TmTcUnixUdpBridge.h +++ b/osal/linux/TmTcUnixUdpBridge.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ #define FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ -#include -#include +#include "../../tmtcservices/AcceptsTelecommandsIF.h" +#include "../../tmtcservices/TmTcBridge.h" #include #include #include From b54d63edcb6077572f7cd61f0b94c96990460b07 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 28 Aug 2020 18:10:02 +0200 Subject: [PATCH 13/20] event manager improvements --- events/EventManager.cpp | 59 +++++++++++++++++++++++------------------ events/EventManager.h | 10 +++++-- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/events/EventManager.cpp b/events/EventManager.cpp index e58f251a..e71951e3 100644 --- a/events/EventManager.cpp +++ b/events/EventManager.cpp @@ -8,13 +8,16 @@ const uint16_t EventManager::POOL_SIZES[N_POOLS] = { sizeof(EventMatchTree::Node), sizeof(EventIdRangeMatcher), sizeof(ReporterRangeMatcher) }; -//If one checks registerListener calls, there are around 40 (to max 50) objects registering for certain events. -//Each listener requires 1 or 2 EventIdMatcher and 1 or 2 ReportRangeMatcher. So a good guess is 75 to a max of 100 pools required for each, which fits well. +// If one checks registerListener calls, there are around 40 (to max 50) +// objects registering for certain events. +// Each listener requires 1 or 2 EventIdMatcher and 1 or 2 ReportRangeMatcher. +// So a good guess is 75 to a max of 100 pools required for each, which fits well. +// SHOULDDO: Shouldn't this be in the config folder and passed via ctor? const uint16_t EventManager::N_ELEMENTS[N_POOLS] = { 240, 120, 120 }; EventManager::EventManager(object_id_t setObjectId) : - SystemObject(setObjectId), eventReportQueue(NULL), mutex(NULL), factoryBackend( - 0, POOL_SIZES, N_ELEMENTS, false, true) { + SystemObject(setObjectId), + factoryBackend(0, POOL_SIZES, N_ELEMENTS, false, true) { mutex = MutexFactory::instance()->createMutex(); eventReportQueue = QueueFactory::instance()->createMessageQueue( MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE); @@ -108,41 +111,45 @@ ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener, #ifdef DEBUG -//forward declaration, should be implemented by mission -const char* translateObject(object_id_t object); -const char * translateEvents(Event event); - void EventManager::printEvent(EventMessage* message) { const char *string = 0; switch (message->getSeverity()) { case SEVERITY::INFO: -// string = translateObject(message->getReporter()); -// sif::info << "EVENT: "; -// if (string != 0) { -// sif::info << string; -// } else { -// sif::info << "0x" << std::hex << message->getReporter() << std::dec; -// } -// sif::info << " reported " << translateEvents(message->getEvent()) << " (" -// << std::dec << message->getEventId() << std::hex << ") P1: 0x" -// << message->getParameter1() << " P2: 0x" -// << message->getParameter2() << std::dec << std::endl; - break; - default: +#ifdef DEBUG_INFO_EVENT string = translateObject(message->getReporter()); - sif::error << "EVENT: "; + sif::info << "EVENT: "; if (string != 0) { - sif::error << string; + sif::info << string; } else { - sif::error << "0x" << std::hex << message->getReporter() << std::dec; + sif::info << "0x" << std::hex << message->getReporter() << std::dec; } - sif::error << " reported " << translateEvents(message->getEvent()) << " (" + sif::info << " reported " << translateEvents(message->getEvent()) << " (" << std::dec << message->getEventId() << std::hex << ") P1: 0x" << message->getParameter1() << " P2: 0x" << message->getParameter2() << std::dec << std::endl; +#endif + break; + default: + string = translateObject(message->getReporter()); + sif::debug << "EventManager: "; + if (string != 0) { + sif::debug << string; + } + else { + sif::debug << "0x" << std::hex << message->getReporter() << std::dec; + } + sif::debug << " reported " << translateEvents(message->getEvent()) + << " (" << std::dec << message->getEventId() << ") " + << std::endl; + + sif::debug << std::hex << "P1 Hex: 0x" << message->getParameter1() + << ", P1 Dec: " << std::dec << message->getParameter1() + << std::endl; + sif::debug << std::hex << "P2 Hex: 0x" << message->getParameter2() + << ", P2 Dec: " << std::dec << message->getParameter2() + << std::endl; break; } - } #endif diff --git a/events/EventManager.h b/events/EventManager.h index 7badc3bf..2602aeb2 100644 --- a/events/EventManager.h +++ b/events/EventManager.h @@ -10,6 +10,12 @@ #include "../ipc/MutexIF.h" #include +#ifdef DEBUG +// forward declaration, should be implemented by mission +extern const char* translateObject(object_id_t object); +extern const char* translateEvents(Event event); +#endif + class EventManager: public EventManagerIF, public ExecutableObjectIF, public SystemObject { @@ -36,11 +42,11 @@ public: ReturnValue_t performOperation(uint8_t opCode); protected: - MessageQueueIF* eventReportQueue; + MessageQueueIF* eventReportQueue = nullptr; std::map listenerList; - MutexIF* mutex; + MutexIF* mutex = nullptr; static const uint8_t N_POOLS = 3; LocalPool factoryBackend; From 7a5c70e75366399082ac9d40a6f95c1c7245cf95 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 28 Aug 2020 18:46:47 +0200 Subject: [PATCH 14/20] typo fixes --- parameters/HasParametersIF.h | 27 +++++-- parameters/ParameterHelper.cpp | 16 ++-- parameters/ParameterHelper.h | 23 ++++-- parameters/ParameterMessage.cpp | 2 +- parameters/ParameterMessage.h | 8 +- parameters/ParameterWrapper.cpp | 31 ++++---- parameters/ParameterWrapper.h | 95 +++++++++++++++--------- parameters/ReceivesParameterMessagesIF.h | 6 +- 8 files changed, 126 insertions(+), 82 deletions(-) diff --git a/parameters/HasParametersIF.h b/parameters/HasParametersIF.h index 71212b57..005403fa 100644 --- a/parameters/HasParametersIF.h +++ b/parameters/HasParametersIF.h @@ -1,12 +1,27 @@ -#ifndef HASPARAMETERSIF_H_ -#define HASPARAMETERSIF_H_ +#ifndef FSFW_PARAMETERS_HASPARAMETERSIF_H_ +#define FSFW_PARAMETERS_HASPARAMETERSIF_H_ -#include "ParameterWrapper.h" +#include "../parameters/ParameterWrapper.h" #include "../returnvalues/HasReturnvaluesIF.h" #include +/** Each parameter is identified with a unique parameter ID */ typedef uint32_t ParameterId_t; +/** + * @brief This interface is used by components which have modifiable + * parameters, e.g. atittude controllers + * @details + * Each parameter has a unique parameter ID. The first byte of the parameter + * ID is the domain ID which can be used to identify unqiue spacecraft domains + * (e.g. control and sensor domain in the AOCS controller). + * + * The second and third byte represent the matrix ID, which can represent + * a 8-bit row and column number and the last byte... + * + * Yeah, it it matrix ID oder parameter ID now and is index a 16 bit number + * of a 8 bit number now? + */ class HasParametersIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::HAS_PARAMETERS_IF; @@ -32,13 +47,11 @@ public: return (domainId << 24) + (parameterId << 8) + index; } - virtual ~HasParametersIF() { - } + virtual ~HasParametersIF() {} /** * Always set parameter before checking newValues! * - * * @param domainId * @param parameterId * @param parameterWrapper @@ -51,4 +64,4 @@ public: const ParameterWrapper *newValues, uint16_t startAtIndex) = 0; }; -#endif /* HASPARAMETERSIF_H_ */ +#endif /* FSFW_PARAMETERS_HASPARAMETERSIF_H_ */ diff --git a/parameters/ParameterHelper.cpp b/parameters/ParameterHelper.cpp index 8543515f..659b00de 100644 --- a/parameters/ParameterHelper.cpp +++ b/parameters/ParameterHelper.cpp @@ -1,11 +1,9 @@ -#include "../objectmanager/ObjectManagerIF.h" #include "ParameterHelper.h" #include "ParameterMessage.h" +#include "../objectmanager/ObjectManagerIF.h" ParameterHelper::ParameterHelper(ReceivesParameterMessagesIF* owner) : - owner(owner), storage(NULL) { - -} + owner(owner) {} ParameterHelper::~ParameterHelper() { } @@ -28,7 +26,6 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) { } break; case ParameterMessage::CMD_PARAMETER_LOAD: { - uint8_t domain = HasParametersIF::getDomain( ParameterMessage::getParameterId(message)); uint16_t parameterId = HasParametersIF::getMatrixId( @@ -36,12 +33,14 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) { uint8_t index = HasParametersIF::getIndex( ParameterMessage::getParameterId(message)); - const uint8_t *storedStream; - size_t storedStreamSize; + const uint8_t *storedStream = nullptr; + size_t storedStreamSize = 0; result = storage->getData( ParameterMessage::getStoreId(message), &storedStream, &storedStreamSize); if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "ParameterHelper::handleParameterMessage: Getting" + " store data failed for load command." << std::endl; break; } @@ -125,7 +124,8 @@ ReturnValue_t ParameterHelper::initialize() { } } -void ParameterHelper::rejectCommand(MessageQueueId_t to, ReturnValue_t reason, Command_t initialCommand) { +void ParameterHelper::rejectCommand(MessageQueueId_t to, ReturnValue_t reason, + Command_t initialCommand) { CommandMessage reply; reply.setReplyRejected(reason, initialCommand); MessageQueueSenderIF::sendMessage(to, &reply, ownerQueueId); diff --git a/parameters/ParameterHelper.h b/parameters/ParameterHelper.h index d887bf1d..595b4bc5 100644 --- a/parameters/ParameterHelper.h +++ b/parameters/ParameterHelper.h @@ -1,9 +1,16 @@ -#ifndef PARAMETERHELPER_H_ -#define PARAMETERHELPER_H_ +#ifndef FSFW_PARAMETERS_PARAMETERHELPER_H_ +#define FSFW_PARAMETERS_PARAMETERHELPER_H_ #include "ParameterMessage.h" #include "ReceivesParameterMessagesIF.h" +#include "../ipc/MessageQueueIF.h" +/** + * @brief Helper class to handle parameter messages. + * @details + * This class simplfies handling of parameter messages, which are sent + * to a class which implements ReceivesParameterMessagesIF. + */ class ParameterHelper { public: ParameterHelper(ReceivesParameterMessagesIF *owner); @@ -15,13 +22,15 @@ public: private: ReceivesParameterMessagesIF *owner; - MessageQueueId_t ownerQueueId; + MessageQueueId_t ownerQueueId = MessageQueueIF::NO_QUEUE; - StorageManagerIF *storage; + StorageManagerIF *storage = nullptr; - ReturnValue_t sendParameter(MessageQueueId_t to, uint32_t id, const ParameterWrapper *description); + ReturnValue_t sendParameter(MessageQueueId_t to, uint32_t id, + const ParameterWrapper *description); - void rejectCommand(MessageQueueId_t to, ReturnValue_t reason, Command_t initialCommand); + void rejectCommand(MessageQueueId_t to, ReturnValue_t reason, + Command_t initialCommand); }; -#endif /* PARAMETERHELPER_H_ */ +#endif /* FSFW_PARAMETERS_PARAMETERHELPER_H_ */ diff --git a/parameters/ParameterMessage.cpp b/parameters/ParameterMessage.cpp index 7e0ed114..e9f3191f 100644 --- a/parameters/ParameterMessage.cpp +++ b/parameters/ParameterMessage.cpp @@ -1,4 +1,4 @@ -#include "ParameterMessage.h" +#include "../parameters/ParameterMessage.h" #include "../objectmanager/ObjectManagerIF.h" ParameterId_t ParameterMessage::getParameterId(const CommandMessage* message) { diff --git a/parameters/ParameterMessage.h b/parameters/ParameterMessage.h index f59af513..31d7fe0b 100644 --- a/parameters/ParameterMessage.h +++ b/parameters/ParameterMessage.h @@ -1,8 +1,8 @@ -#ifndef PARAMETERMESSAGE_H_ -#define PARAMETERMESSAGE_H_ +#ifndef FSFW_PARAMETERS_PARAMETERMESSAGE_H_ +#define FSFW_PARAMETERS_PARAMETERMESSAGE_H_ -#include "../ipc/CommandMessage.h" #include "HasParametersIF.h" +#include "../ipc/CommandMessage.h" #include "../storagemanager/StorageManagerIF.h" class ParameterMessage { @@ -26,4 +26,4 @@ public: }; -#endif /* PARAMETERMESSAGE_H_ */ +#endif /* FSFW_PARAMETERS_PARAMETERMESSAGE_H_ */ diff --git a/parameters/ParameterWrapper.cpp b/parameters/ParameterWrapper.cpp index 56f56426..d020da33 100644 --- a/parameters/ParameterWrapper.cpp +++ b/parameters/ParameterWrapper.cpp @@ -1,20 +1,19 @@ #include "ParameterWrapper.h" ParameterWrapper::ParameterWrapper() : - pointsToStream(false), type(Type::UNKNOWN_TYPE), rows(0), columns(0), data( - NULL), readonlyData(NULL) { + pointsToStream(false), type(Type::UNKNOWN_TYPE) { } ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data) : - pointsToStream(false), type(type), rows(rows), columns(columns), data( - data), readonlyData(data) { + pointsToStream(false), type(type), rows(rows), columns(columns), + data(data), readonlyData(data) { } ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns, const void *data) : - pointsToStream(false), type(type), rows(rows), columns(columns), data( - NULL), readonlyData(data) { + pointsToStream(false), type(type), rows(rows), columns(columns), + data(nullptr), readonlyData(data) { } ParameterWrapper::~ParameterWrapper() { @@ -141,6 +140,7 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow, } + ReturnValue_t ParameterWrapper::deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) { return deSerialize(buffer, size, streamEndianness, 0); @@ -184,16 +184,16 @@ ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize, return SerializeIF::STREAM_TOO_SHORT; } - data = NULL; + data = nullptr; readonlyData = stream; pointsToStream = true; stream += dataSize; - if (remainingStream != NULL) { + if (remainingStream != nullptr) { *remainingStream = stream; } streamSize -= dataSize; - if (remainingSize != NULL) { + if (remainingSize != nullptr) { *remainingSize = streamSize; } @@ -265,15 +265,14 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from, result = UNKNOW_DATATYPE; break; } - } else { + } + else { //need a type to do arithmetic - uint8_t *toDataWithType = (uint8_t*) data; + uint8_t* typedData = static_cast(data); for (uint8_t fromRow = 0; fromRow < from->rows; fromRow++) { - memcpy( - toDataWithType - + (((startingRow + fromRow) * columns) - + startingColumn) * typeSize, - from->readonlyData, typeSize * from->columns); + uint8_t offset = (((startingRow + fromRow) * columns) + startingColumn) * typeSize; + std::memcpy(typedData + offset, from->readonlyData, + typeSize * from->columns); } } diff --git a/parameters/ParameterWrapper.h b/parameters/ParameterWrapper.h index b18fe2b9..f07205d4 100644 --- a/parameters/ParameterWrapper.h +++ b/parameters/ParameterWrapper.h @@ -1,12 +1,16 @@ -#ifndef PARAMETERWRAPPER_H_ -#define PARAMETERWRAPPER_H_ +#ifndef FSFW_PARAMETERS_PARAMETERWRAPPER_H_ +#define FSFW_PARAMETERS_PARAMETERWRAPPER_H_ #include "../returnvalues/HasReturnvaluesIF.h" #include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeIF.h" -#include #include "../globalfunctions/Type.h" +#include +/** + * @brief + * @details + */ class ParameterWrapper: public SerializeIF { friend class DataPoolParameterWrapper; public: @@ -36,32 +40,21 @@ public: virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness, uint16_t startWritingAtIndex = 0); + /** + * Get a specific parameter value by supplying the row and the column. + * @tparam T Type of target data + * @param value [out] Pointer to storage location + * @param row + * @param column + * @return + * -@c RETURN_OK if element was retrieved successfully + * -@c NOT_SET data has not been set yet + * -@c DATATYPE_MISSMATCH Invalid supplied type + * -@c OUT_OF_BOUNDS Invalid row and/or column. + */ template - ReturnValue_t getElement(T *value, uint8_t row = 0, uint8_t column = 0) const { - if (readonlyData == NULL){ - return NOT_SET; - } - - if (PodTypeConversion::type != type) { - return DATATYPE_MISSMATCH; - } - - if ((row >= rows) || (column >= columns)) { - return OUT_OF_BOUNDS; - } - - if (pointsToStream) { - const uint8_t *streamWithtype = (const uint8_t *) readonlyData; - streamWithtype += (row * columns + column) * type.getSize(); - int32_t size = type.getSize(); - return SerializeAdapter::deSerialize(value, &streamWithtype, - &size, true); - } else { - const T *dataWithType = (const T *) readonlyData; - *value = dataWithType[row * columns + column]; - return HasReturnvaluesIF::RETURN_OK; - } - } + ReturnValue_t getElement(T *value, uint8_t row = 0, + uint8_t column = 0) const; template void set(T *data, uint8_t rows, uint8_t columns) { @@ -111,21 +104,22 @@ public: void setMatrix(const T& member) { this->set(member[0], sizeof(member)/sizeof(member[0]), sizeof(member[0])/sizeof(member[0][0])); } + ReturnValue_t set(const uint8_t *stream, size_t streamSize, - const uint8_t **remainingStream = NULL, size_t *remainingSize = - NULL); + const uint8_t **remainingStream = nullptr, + size_t *remainingSize = nullptr); ReturnValue_t copyFrom(const ParameterWrapper *from, uint16_t startWritingAtIndex); private: - bool pointsToStream; + bool pointsToStream = false; Type type; - uint8_t rows; - uint8_t columns; - void *data; - const void *readonlyData; + uint8_t rows = 0; + uint8_t columns = 0; + void *data = nullptr; + const void *readonlyData = nullptr; template ReturnValue_t serializeData(uint8_t** buffer, size_t* size, @@ -136,4 +130,33 @@ private: const void *from, uint8_t fromRows, uint8_t fromColumns); }; -#endif /* PARAMETERWRAPPER_H_ */ +template +inline ReturnValue_t ParameterWrapper::getElement(T *value, uint8_t row, + uint8_t column) const { + if (readonlyData == nullptr){ + return NOT_SET; + } + + if (PodTypeConversion::type != type) { + return DATATYPE_MISSMATCH; + } + + if ((row >= rows) or (column >= columns)) { + return OUT_OF_BOUNDS; + } + + if (pointsToStream) { + const uint8_t *streamWithType = static_cast(readonlyData); + streamWithType += (row * columns + column) * type.getSize(); + int32_t size = type.getSize(); + return SerializeAdapter::deSerialize(value, &streamWithType, + &size, true); + } + else { + const T *dataWithType = static_cast(readonlyData); + *value = dataWithType[row * columns + column]; + return HasReturnvaluesIF::RETURN_OK; + } +} + +#endif /* FSFW_PARAMETERS_PARAMETERWRAPPER_H_ */ diff --git a/parameters/ReceivesParameterMessagesIF.h b/parameters/ReceivesParameterMessagesIF.h index 1fcbd4b3..e8c7fa69 100644 --- a/parameters/ReceivesParameterMessagesIF.h +++ b/parameters/ReceivesParameterMessagesIF.h @@ -1,5 +1,5 @@ -#ifndef RECEIVESPARAMETERMESSAGESIF_H_ -#define RECEIVESPARAMETERMESSAGESIF_H_ +#ifndef FSFW_PARAMETERS_RECEIVESPARAMETERMESSAGESIF_H_ +#define FSFW_PARAMETERS_RECEIVESPARAMETERMESSAGESIF_H_ #include "HasParametersIF.h" @@ -16,4 +16,4 @@ public: }; -#endif /* RECEIVESPARAMETERMESSAGESIF_H_ */ +#endif /* FSFW_PARAMETERS_RECEIVESPARAMETERMESSAGESIF_H_ */ From 695a4e7842f367d35c532f921cea1ad5ffb41dba Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Sep 2020 12:42:52 +0200 Subject: [PATCH 15/20] offset is size_t now --- parameters/ParameterWrapper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/parameters/ParameterWrapper.cpp b/parameters/ParameterWrapper.cpp index d020da33..6adc6857 100644 --- a/parameters/ParameterWrapper.cpp +++ b/parameters/ParameterWrapper.cpp @@ -270,7 +270,8 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from, //need a type to do arithmetic uint8_t* typedData = static_cast(data); for (uint8_t fromRow = 0; fromRow < from->rows; fromRow++) { - uint8_t offset = (((startingRow + fromRow) * columns) + startingColumn) * typeSize; + size_t offset = (((startingRow + fromRow) * columns) + + startingColumn) * typeSize; std::memcpy(typedData + offset, from->readonlyData, typeSize * from->columns); } From b522b3c29c5d1490c8b8d0fd2dc4209fd92cd9b9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Sep 2020 12:53:53 +0200 Subject: [PATCH 16/20] fifo updates --- container/DynamicFIFO.h | 4 ++-- container/FIFO.h | 12 +++++++----- container/FIFOBase.h | 2 +- container/FIFOBase.tpp | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/container/DynamicFIFO.h b/container/DynamicFIFO.h index 7fa0c32c..abb53330 100644 --- a/container/DynamicFIFO.h +++ b/container/DynamicFIFO.h @@ -22,7 +22,7 @@ public: // trying to pass the pointer of the uninitialized vector // to the FIFOBase constructor directly lead to a super evil bug. // So we do it like this now. - this->setData(fifoVector.data()); + this->setContainer(fifoVector.data()); }; /** @@ -31,7 +31,7 @@ public: */ DynamicFIFO(const DynamicFIFO& other): FIFOBase(other), fifoVector(other.maxCapacity) { - this->setData(fifoVector.data()); + this->setContainer(fifoVector.data()); } diff --git a/container/FIFO.h b/container/FIFO.h index e60a4979..19f763fc 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_CONTAINER_FIFO_H_ -#define FRAMEWORK_CONTAINER_FIFO_H_ +#ifndef FSFW_CONTAINER_FIFO_H_ +#define FSFW_CONTAINER_FIFO_H_ #include "FIFOBase.h" #include @@ -16,18 +16,20 @@ template class FIFO: public FIFOBase { public: - FIFO(): FIFOBase(fifoArray.data(), capacity) {}; + FIFO(): FIFOBase(nullptr, capacity) { + this->setContainer(fifoArray.data()); + }; /** * @brief Custom copy constructor to set pointer correctly. * @param other */ FIFO(const FIFO& other): FIFOBase(other) { - this->setData(fifoArray.data()); + this->setContainer(fifoArray.data()); } private: std::array fifoArray; }; -#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ +#endif /* FSFW_CONTAINER_FIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h index bbabd67c..b744706d 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -48,7 +48,7 @@ public: size_t getMaxCapacity() const; protected: - void setData(T* data); + void setContainer(T* data); size_t maxCapacity = 0; T* values; diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp index e1287dcf..d54b3f8f 100644 --- a/container/FIFOBase.tpp +++ b/container/FIFOBase.tpp @@ -80,7 +80,7 @@ inline size_t FIFOBase::getMaxCapacity() const { template -inline void FIFOBase::setData(T *data) { +inline void FIFOBase::setContainer(T *data) { this->values = data; } From 03b2ca679d81d15d0c449e9c44b515647c6623c2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Sep 2020 12:58:29 +0200 Subject: [PATCH 17/20] include guard correction --- tmtcservices/CommandingServiceBase.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index a774e7ae..864a0614 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ -#define FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ +#ifndef FSFW_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ +#define FSFW_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ #include "../objectmanager/SystemObject.h" #include "../storagemanager/StorageManagerIF.h" @@ -345,4 +345,4 @@ private: void checkTimeout(); }; -#endif /* FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ */ +#endif /* FSFW_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ */ From 234fbcbf417d201922e13e98c0a6fe7bda37a967 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 6 Sep 2020 09:34:06 +0200 Subject: [PATCH 18/20] small bugfix in error checking --- osal/linux/TmTcUnixUdpBridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp index 46b26254..80d02b25 100644 --- a/osal/linux/TmTcUnixUdpBridge.cpp +++ b/osal/linux/TmTcUnixUdpBridge.cpp @@ -24,7 +24,7 @@ TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, // Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html //clientSocket = socket(AF_INET, SOCK_DGRAM, 0); serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if(socket < 0) { + if(serverSocket < 0) { sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open" " UDP socket!" << std::endl; handleSocketError(); From 2439ac455be631938c69fe6400ed025f7eaaaaa5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 6 Sep 2020 15:48:30 +0200 Subject: [PATCH 19/20] tmtc bridge update, uses dynamic FIFO now --- tmtcservices/TmTcBridge.cpp | 108 ++++++++++++++++++++++-------------- tmtcservices/TmTcBridge.h | 20 +++++-- 2 files changed, 81 insertions(+), 47 deletions(-) diff --git a/tmtcservices/TmTcBridge.cpp b/tmtcservices/TmTcBridge.cpp index 021b0d7b..8c2f15e5 100644 --- a/tmtcservices/TmTcBridge.cpp +++ b/tmtcservices/TmTcBridge.cpp @@ -1,7 +1,7 @@ -#include "TmTcBridge.h" +#include "../tmtcservices/TmTcBridge.h" #include "../ipc/QueueFactory.h" -#include "AcceptsTelecommandsIF.h" +#include "../tmtcservices/AcceptsTelecommandsIF.h" #include "../serviceinterface/ServiceInterfaceStream.h" #include "../globalfunctions/arrayprinter.h" @@ -66,6 +66,8 @@ ReturnValue_t TmTcBridge::initialize() { return ObjectManagerIF::CHILD_INIT_FAILED; } + tmFifo = new DynamicFIFO(maxNumberOfPacketsStored); + tmTcReceptionQueue->setDefaultDestination(tcDistributor->getRequestQueue()); return RETURN_OK; } @@ -90,102 +92,122 @@ ReturnValue_t TmTcBridge::handleTc() { } ReturnValue_t TmTcBridge::handleTm() { + ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = handleTmQueue(); if(result != RETURN_OK) { - sif::warning << "TmTcBridge: Reading TM Queue failed" << std::endl; - return RETURN_FAILED; + sif::error << "TmTcBridge::handleTm: Error handling TM queue!" + << std::endl; + status = result; } - if(tmStored and communicationLinkUp) { - result = handleStoredTm(); + if(tmStored and communicationLinkUp and + (packetSentCounter < sentPacketsPerCycle)) { + result = handleStoredTm(); + if(result != RETURN_OK) { + sif::error << "TmTcBridge::handleTm: Error handling stored TMs!" + << std::endl; + status = result; + } } - return result; - + packetSentCounter = 0; + return status; } ReturnValue_t TmTcBridge::handleTmQueue() { TmTcMessage message; const uint8_t* data = nullptr; size_t size = 0; + ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; for (ReturnValue_t result = tmTcReceptionQueue->receiveMessage(&message); - result == RETURN_OK; result = tmTcReceptionQueue->receiveMessage(&message)) + result == HasReturnvaluesIF::RETURN_OK; + result = tmTcReceptionQueue->receiveMessage(&message)) { - if(communicationLinkUp == false) { - result = storeDownlinkData(&message); - return result; + //sif::info << (int) packetSentCounter << std::endl; + if(communicationLinkUp == false or + packetSentCounter >= sentPacketsPerCycle) { + storeDownlinkData(&message); + continue; } result = tmStore->getData(message.getStorageId(), &data, &size); if (result != HasReturnvaluesIF::RETURN_OK) { + status = result; continue; } result = sendTm(data, size); - if (result != RETURN_OK) { - sif::warning << "TmTcBridge: Could not send TM packet" << std::endl; - tmStore->deleteData(message.getStorageId()); - return result; - + if (result != HasReturnvaluesIF::RETURN_OK) { + status = result; + } + else { + tmStore->deleteData(message.getStorageId()); + packetSentCounter++; } - tmStore->deleteData(message.getStorageId()); } - return RETURN_OK; + return status; } ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage *message) { store_address_t storeId = 0; - if(tmFifo.full()) { - sif::error << "TmTcBridge::storeDownlinkData: TM downlink max. number " - << "of stored packet IDs reached! " - << "Overwriting old data" << std::endl; - tmFifo.retrieve(&storeId); - tmStore->deleteData(storeId); + if(tmFifo->full()) { + sif::debug << "TmTcBridge::storeDownlinkData: TM downlink max. number " + << "of stored packet IDs reached! " << std::endl; + if(overwriteOld) { + tmFifo->retrieve(&storeId); + tmStore->deleteData(storeId); + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } } + storeId = message->getStorageId(); - tmFifo.insert(storeId); + tmFifo->insert(storeId); tmStored = true; return RETURN_OK; } ReturnValue_t TmTcBridge::handleStoredTm() { - uint8_t counter = 0; - ReturnValue_t result = RETURN_OK; - while(not tmFifo.empty() and counter < sentPacketsPerCycle) { - //info << "TMTC Bridge: Sending stored TM data. There are " - // << (int) fifo.size() << " left to send\r\n" << std::flush; + ReturnValue_t status = RETURN_OK; + while(not tmFifo->empty() and packetSentCounter < sentPacketsPerCycle) { + //sif::info << "TMTC Bridge: Sending stored TM data. There are " + // << (int) tmFifo->size() << " left to send\r\n" << std::flush; + store_address_t storeId; const uint8_t* data = nullptr; size_t size = 0; - tmFifo.retrieve(&storeId); - result = tmStore->getData(storeId, &data, &size); - - sendTm(data,size); + tmFifo->retrieve(&storeId); + ReturnValue_t result = tmStore->getData(storeId, &data, &size); + if(result != HasReturnvaluesIF::RETURN_OK) { + status = result; + } + result = sendTm(data,size); if(result != RETURN_OK) { sif::error << "TMTC Bridge: Could not send stored downlink data" << std::endl; - result = RETURN_FAILED; + status = result; } - counter ++; + packetSentCounter ++; - if(tmFifo.empty()) { + if(tmFifo->empty()) { tmStored = false; } tmStore->deleteData(storeId); } - return result; + return status; } void TmTcBridge::registerCommConnect() { if(not communicationLinkUp) { - //info << "TMTC Bridge: Registered Comm Link Connect" << std::endl; + //sif::info << "TMTC Bridge: Registered Comm Link Connect" << std::endl; communicationLinkUp = true; } } void TmTcBridge::registerCommDisconnect() { - //info << "TMTC Bridge: Registered Comm Link Disconnect" << std::endl; + //sif::info << "TMTC Bridge: Registered Comm Link Disconnect" << std::endl; if(communicationLinkUp) { communicationLinkUp = false; } @@ -209,3 +231,7 @@ MessageQueueId_t TmTcBridge::getRequestQueue() { // Default implementation: Relay TC messages to TC distributor directly. return tmTcReceptionQueue->getDefaultDestination(); } + +void TmTcBridge::setFifoToOverwriteOldData(bool overwriteOld) { + this->overwriteOld = overwriteOld; +} diff --git a/tmtcservices/TmTcBridge.h b/tmtcservices/TmTcBridge.h index 32eaf7f2..62cfdaac 100644 --- a/tmtcservices/TmTcBridge.h +++ b/tmtcservices/TmTcBridge.h @@ -1,15 +1,15 @@ #ifndef FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ #define FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ + #include "../objectmanager/SystemObject.h" -#include "AcceptsTelemetryIF.h" +#include "../tmtcservices/AcceptsTelemetryIF.h" #include "../tasks/ExecutableObjectIF.h" #include "../ipc/MessageQueueIF.h" #include "../storagemanager/StorageManagerIF.h" -#include "AcceptsTelecommandsIF.h" - -#include "../container/FIFO.h" -#include "TmTcMessage.h" +#include "../tmtcservices/AcceptsTelecommandsIF.h" +#include "../container/DynamicFIFO.h" +#include "../tmtcservices/TmTcMessage.h" class TmTcBridge : public AcceptsTelemetryIF, public AcceptsTelecommandsIF, @@ -46,6 +46,12 @@ public: */ ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored); + /** + * This will set up the bridge to overwrite old data in the FIFO. + * @param overwriteOld + */ + void setFifoToOverwriteOldData(bool overwriteOld); + virtual void registerCommConnect(); virtual void registerCommDisconnect(); @@ -86,6 +92,8 @@ protected: //! by default, so telemetry will be handled immediately. bool communicationLinkUp = true; bool tmStored = false; + bool overwriteOld = true; + uint8_t packetSentCounter = 0; /** * @brief Handle TC reception @@ -145,7 +153,7 @@ protected: * This fifo can be used to store downlink data * which can not be sent at the moment. */ - FIFO tmFifo; + DynamicFIFO* tmFifo = nullptr; uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE; uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED; }; From 6c42189371dd76082fe93e7f832c509e8967b402 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 6 Sep 2020 15:49:32 +0200 Subject: [PATCH 20/20] some minor improvements --- osal/linux/TcUnixUdpPollingTask.cpp | 1 + osal/linux/TmTcUnixUdpBridge.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osal/linux/TcUnixUdpPollingTask.cpp b/osal/linux/TcUnixUdpPollingTask.cpp index 95910b02..670ba804 100644 --- a/osal/linux/TcUnixUdpPollingTask.cpp +++ b/osal/linux/TcUnixUdpPollingTask.cpp @@ -120,6 +120,7 @@ void TcUnixUdpPollingTask::setTimeout(double timeoutSeconds) { } } +// TODO: sleep after error detection to prevent spam void TcUnixUdpPollingTask::handleReadError() { switch(errno) { case(EAGAIN): { diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp index 80d02b25..b55291b3 100644 --- a/osal/linux/TmTcUnixUdpBridge.cpp +++ b/osal/linux/TmTcUnixUdpBridge.cpp @@ -5,6 +5,7 @@ #include #include + TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId, uint16_t serverPort, uint16_t clientPort): @@ -100,8 +101,8 @@ void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) { } } -void TmTcUnixUdpBridge::handleSocketError() { +void TmTcUnixUdpBridge::handleSocketError() { // See: https://man7.org/linux/man-pages/man2/socket.2.html switch(errno) { case(EACCES): @@ -162,7 +163,8 @@ void TmTcUnixUdpBridge::handleBindError() { void TmTcUnixUdpBridge::handleSendError() { switch(errno) { default: - sif::error << "Error: " << strerror(errno) << std::endl; + sif::error << "TmTcUnixBridge::handleSendError: " + << strerror(errno) << std::endl; } }