From fe246b9bca27038708bd2d0380d198966b951b9a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Apr 2020 11:43:37 +0200 Subject: [PATCH 1/6] fixed map improvements --- container/FixedMap.h | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/container/FixedMap.h b/container/FixedMap.h index 0b84bf4e..7f3d28f7 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -6,7 +6,11 @@ #include /** - * \ingroup container + * @brief Map implementation for maps with a pre-defined size. + * @details Can be initialized with desired maximum size. + * Iterator is used to access pair and + * iterate through map entries. Complexity O(n). + * @ingroup container */ template class FixedMap: public SerializeIF { @@ -52,12 +56,24 @@ public: return ArrayList, uint32_t>::Iterator::value->second; } + // -> operator overloaded, can be used to access value T *operator->() { return &ArrayList, uint32_t>::Iterator::value->second; } + // Can be used to access the key of the iterator + key_t first() { + return ArrayList, uint32_t>::Iterator::value->first; + } + + // Alternative to access value, similar to std::map implementation + T second() { + return ArrayList, uint32_t>::Iterator::value->second; + } }; + + Iterator begin() const { return Iterator(&theMap[0]); } @@ -72,10 +88,10 @@ public: ReturnValue_t insert(key_t key, T value, Iterator *storedValue = NULL) { if (exists(key) == HasReturnvaluesIF::RETURN_OK) { - return KEY_ALREADY_EXISTS; + return FixedMap::KEY_ALREADY_EXISTS; } if (_size == theMap.maxSize()) { - return MAP_FULL; + return FixedMap::MAP_FULL; } theMap[_size].first = key; theMap[_size].second = value; @@ -87,7 +103,7 @@ public: } ReturnValue_t insert(std::pair pair) { - return insert(pair.fist, pair.second); + return insert(pair.first, pair.second); } ReturnValue_t exists(key_t key) const { @@ -148,8 +164,17 @@ public: return theMap.maxSize(); } - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { + bool full() { + if(_size == theMap.maxSize()) { + return true; + } + else { + return false; + } + } + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + const size_t max_size, bool bigEndian) const { ReturnValue_t result = SerializeAdapter::serialize(&this->_size, buffer, size, max_size, bigEndian); uint32_t i = 0; @@ -163,7 +188,7 @@ public: return result; } - virtual uint32_t getSerializedSize() const { + virtual size_t getSerializedSize() const { uint32_t printSize = sizeof(_size); uint32_t i = 0; @@ -176,7 +201,7 @@ public: return printSize; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, bool bigEndian) { ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size, buffer, size, bigEndian); From 826e2bdb2dfbfad69919ccb856a7835219bc1075 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Apr 2020 15:10:23 +0200 Subject: [PATCH 2/6] Revert "fixed map improvements" This reverts commit fe246b9bca27038708bd2d0380d198966b951b9a. --- container/FixedMap.h | 41 ++++++++--------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/container/FixedMap.h b/container/FixedMap.h index 7f3d28f7..0b84bf4e 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -6,11 +6,7 @@ #include /** - * @brief Map implementation for maps with a pre-defined size. - * @details Can be initialized with desired maximum size. - * Iterator is used to access pair and - * iterate through map entries. Complexity O(n). - * @ingroup container + * \ingroup container */ template class FixedMap: public SerializeIF { @@ -56,24 +52,12 @@ public: return ArrayList, uint32_t>::Iterator::value->second; } - // -> operator overloaded, can be used to access value T *operator->() { return &ArrayList, uint32_t>::Iterator::value->second; } - // Can be used to access the key of the iterator - key_t first() { - return ArrayList, uint32_t>::Iterator::value->first; - } - - // Alternative to access value, similar to std::map implementation - T second() { - return ArrayList, uint32_t>::Iterator::value->second; - } }; - - Iterator begin() const { return Iterator(&theMap[0]); } @@ -88,10 +72,10 @@ public: ReturnValue_t insert(key_t key, T value, Iterator *storedValue = NULL) { if (exists(key) == HasReturnvaluesIF::RETURN_OK) { - return FixedMap::KEY_ALREADY_EXISTS; + return KEY_ALREADY_EXISTS; } if (_size == theMap.maxSize()) { - return FixedMap::MAP_FULL; + return MAP_FULL; } theMap[_size].first = key; theMap[_size].second = value; @@ -103,7 +87,7 @@ public: } ReturnValue_t insert(std::pair pair) { - return insert(pair.first, pair.second); + return insert(pair.fist, pair.second); } ReturnValue_t exists(key_t key) const { @@ -164,17 +148,8 @@ public: return theMap.maxSize(); } - bool full() { - if(_size == theMap.maxSize()) { - return true; - } - else { - return false; - } - } - - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - const size_t max_size, bool bigEndian) const { + virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, + const uint32_t max_size, bool bigEndian) const { ReturnValue_t result = SerializeAdapter::serialize(&this->_size, buffer, size, max_size, bigEndian); uint32_t i = 0; @@ -188,7 +163,7 @@ public: return result; } - virtual size_t getSerializedSize() const { + virtual uint32_t getSerializedSize() const { uint32_t printSize = sizeof(_size); uint32_t i = 0; @@ -201,7 +176,7 @@ public: return printSize; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size, + virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size, buffer, size, bigEndian); From 2a72e94d6f4fde6653c3ead47d0d9d26b90e6712 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 8 Apr 2020 19:33:01 +0200 Subject: [PATCH 3/6] new stopwatch :-) --- osal/FreeRTOS/Clock.cpp | 4 +- osal/FreeRTOS/Timekeeper.cpp | 26 ++++++++----- osal/FreeRTOS/Timekeeper.h | 9 ++++- timemanager/Clock.h | 3 +- timemanager/Stopwatch.cpp | 61 +++++++++++++++++++++++++++++++ timemanager/Stopwatch.h | 71 ++++++++++++++++++++++++++++++++++++ 6 files changed, 161 insertions(+), 13 deletions(-) create mode 100644 timemanager/Stopwatch.cpp create mode 100644 timemanager/Stopwatch.h diff --git a/osal/FreeRTOS/Clock.cpp b/osal/FreeRTOS/Clock.cpp index cffc2125..5e597f25 100644 --- a/osal/FreeRTOS/Clock.cpp +++ b/osal/FreeRTOS/Clock.cpp @@ -3,8 +3,11 @@ #include #include "Timekeeper.h" +extern "C" { #include #include +} + //TODO sanitize input? //TODO much of this code can be reused for tick-only systems @@ -56,7 +59,6 @@ ReturnValue_t Clock::getUptime(timeval* uptime) { timeval Clock::getUptime() { TickType_t ticksSinceStart = xTaskGetTickCount(); - return Timekeeper::ticksToTimeval(ticksSinceStart); } diff --git a/osal/FreeRTOS/Timekeeper.cpp b/osal/FreeRTOS/Timekeeper.cpp index 81f7f997..949e1df3 100644 --- a/osal/FreeRTOS/Timekeeper.cpp +++ b/osal/FreeRTOS/Timekeeper.cpp @@ -1,20 +1,24 @@ -#include "Timekeeper.h" -#include +/** + * @file Timekeeper.cpp + * @date + */ -Timekeeper::Timekeeper() : - offset( { 0, 0 }) { - // TODO Auto-generated constructor stub +#include +extern "C" { +#include } -Timekeeper * Timekeeper::myinstance = NULL; +Timekeeper * Timekeeper::myinstance = nullptr; + +Timekeeper::Timekeeper() : offset( { 0, 0 }) {} const timeval& Timekeeper::getOffset() const { return offset; } Timekeeper* Timekeeper::instance() { - if (myinstance == NULL) { + if (myinstance == nullptr) { myinstance = new Timekeeper(); } return myinstance; @@ -24,9 +28,7 @@ void Timekeeper::setOffset(const timeval& offset) { this->offset = offset; } -Timekeeper::~Timekeeper() { - // TODO Auto-generated destructor stub -} +Timekeeper::~Timekeeper() {} timeval Timekeeper::ticksToTimeval(TickType_t ticks) { timeval uptime; @@ -40,3 +42,7 @@ timeval Timekeeper::ticksToTimeval(TickType_t ticks) { return uptime; } + +TickType_t Timekeeper::getTicks() { + return xTaskGetTickCount(); +} diff --git a/osal/FreeRTOS/Timekeeper.h b/osal/FreeRTOS/Timekeeper.h index 2ba3e4a9..05f0f701 100644 --- a/osal/FreeRTOS/Timekeeper.h +++ b/osal/FreeRTOS/Timekeeper.h @@ -2,8 +2,10 @@ #define FRAMEWORK_OSAL_FREERTOS_TIMEKEEPER_H_ #include - +extern "C" { #include +} + /** * A Class to basically store the time difference between uptime and UTC @@ -25,6 +27,11 @@ public: virtual ~Timekeeper(); static timeval ticksToTimeval(TickType_t ticks); + /** + * Get elapsed time in system ticks. + * @return + */ + static TickType_t getTicks(); const timeval& getOffset() const; void setOffset(const timeval& offset); diff --git a/timemanager/Clock.h b/timemanager/Clock.h index af657247..5f18de3e 100644 --- a/timemanager/Clock.h +++ b/timemanager/Clock.h @@ -7,7 +7,8 @@ #include #include - +typedef uint32_t millis_t; +typedef float seconds_t; class Clock { public: diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp new file mode 100644 index 00000000..6c50f0de --- /dev/null +++ b/timemanager/Stopwatch.cpp @@ -0,0 +1,61 @@ +/** + * @file Stopwatch.cpp + * + * @date 08.04.2020 + */ + +#include +#include +#include + +Stopwatch::Stopwatch(bool displayOnDestruction, + StopwatchDisplayMode displayMode): displayMode(displayMode), + displayOnDestruction(displayOnDestruction) { + // Measures start time on initialization. + Clock::getUptime(&startTime); +} + +void Stopwatch::start() { + startTime = Clock::getUptime(); +} + +millis_t Stopwatch::stop() { + stopInternal(); + return elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000; +} + +seconds_t Stopwatch::stopSeconds() { + stopInternal(); + return timevalOperations::toDouble(elapsedTime); +} + +void Stopwatch::display() { + if(displayMode == StopwatchDisplayMode::MILLIS) { + info << "Stopwatch: Operation took " << elapsedTime.tv_sec * 1000 + + elapsedTime.tv_usec * 1000 << " milliseconds" << std::endl; + } + else if(displayMode == StopwatchDisplayMode::SECONDS) { + info <<"Stopwatch: Operation took " << std::setprecision(3) + << std::fixed << timevalOperations::toDouble(elapsedTime) + << " seconds" << std::endl; + } +} + +Stopwatch::~Stopwatch() { + if(displayOnDestruction) { + stopInternal(); + display(); + } +} + +void Stopwatch::setDisplayMode(StopwatchDisplayMode displayMode) { + this->displayMode = displayMode; +} + +StopwatchDisplayMode Stopwatch::getDisplayMode() const { + return displayMode; +} + +void Stopwatch::stopInternal() { + elapsedTime = Clock::getUptime() - startTime; +} diff --git a/timemanager/Stopwatch.h b/timemanager/Stopwatch.h new file mode 100644 index 00000000..786a9d57 --- /dev/null +++ b/timemanager/Stopwatch.h @@ -0,0 +1,71 @@ +/** + * @file Stopwatch.h + * + * @date 08.04.2020 + */ + +#ifndef FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ +#define FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ +#include + +enum class StopwatchDisplayMode { + MILLIS, + SECONDS +}; + +/** + * @brief Simple Stopwatch implementation to measure elapsed time + * @details + * This class can be used to measure elapsed times. It also displays elapsed + * times automatically on destruction if not explicitely deactivated in the + * constructor. The default time format is the elapsed time in miliseconds + * as a float. + */ +class Stopwatch { +public: + /** + * Default constructor. Call "Stopwatch stopwatch" without brackets if + * no parameters are required! + * @param displayOnDestruction If set to true, displays measured time on + * object destruction + * @param displayMode Display format is either MS rounded or MS as double + * format + * @param outputPrecision If using double format, specify precision here. + */ + Stopwatch(bool displayOnDestruction = true, StopwatchDisplayMode displayMode + = StopwatchDisplayMode::MILLIS); + virtual~ Stopwatch(); + + /** + * Caches the start time + */ + void start(); + + /** + * Calculates the elapsed time since start and returns it + * @return elapsed time in milliseconds (rounded) + */ + millis_t stop(); + seconds_t stopSeconds(); + + /** + * Displays the elapsed times on the osstream, depending on internal display + * mode. + */ + void display(); + + StopwatchDisplayMode getDisplayMode() const; + void setDisplayMode(StopwatchDisplayMode displayMode); +private: + timeval startTime {0, 0}; + timeval elapsedTime {0, 0}; + + StopwatchDisplayMode displayMode = StopwatchDisplayMode::MILLIS; + bool displayOnDestruction = true; + void stopInternal(); +}; + + + + +#endif /* FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ */ From bd0b9cb877ec6138d6d83727480748d4a676975e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 16 Apr 2020 09:30:02 +0200 Subject: [PATCH 4/6] catch example informative comment --- test/CatchExample.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/CatchExample.cpp b/test/CatchExample.cpp index 4db6a5c2..90fd1ed5 100644 --- a/test/CatchExample.cpp +++ b/test/CatchExample.cpp @@ -1,5 +1,7 @@ // Catch Example. // Does not work yet. Problems with linker without main and config folder. +// propably because global object manager and some config files are not supplied +// but mandatory for full compilation of the framework. // Let Catch provide main(): #if defined(UNIT_TEST) From 33b834ad910ca269c4131d8b796c2deba94a2eed Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 16 Apr 2020 10:43:50 +0200 Subject: [PATCH 5/6] null replaced by nullptr --- devicehandlers/DeviceHandlerBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 5fb5a9e5..374ebaf6 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -114,7 +114,7 @@ ReturnValue_t DeviceHandlerBase::initialize() { AcceptsDeviceResponsesIF *rawReceiver = objectManager->get< AcceptsDeviceResponsesIF>(rawDataReceiverId); - if (rawReceiver == NULL) { + if (rawReceiver == nullptr) { return RETURN_FAILED; } From f45a8cc17193fb3176a8410bd8b00e4ca351bad9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 16 Apr 2020 13:17:26 +0200 Subject: [PATCH 6/6] fixed slot sequence safety check added --- devicehandlers/FixedSlotSequence.cpp | 11 ++++++++++- devicehandlers/FixedSlotSequence.h | 4 +++- osal/FreeRTOS/FixedTimeslotTask.cpp | 1 - 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/devicehandlers/FixedSlotSequence.cpp b/devicehandlers/FixedSlotSequence.cpp index 23bb0e78..f11de94b 100644 --- a/devicehandlers/FixedSlotSequence.cpp +++ b/devicehandlers/FixedSlotSequence.cpp @@ -1,5 +1,6 @@ #include #include +#include FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : slotLengthMs(setLengthMs) { @@ -87,7 +88,15 @@ uint32_t FixedSlotSequence::getLengthMs() const { } ReturnValue_t FixedSlotSequence::checkSequence() const { - // Iterate through slotList and check successful creation. + if(slotList.empty()) { + error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; + // does check sequence have to be const? + // if I want to check a class, I need the ability to set + // internal class states. + //isEmpty = true; + std::exit(0); + } + // Iterate through slotList and check successful creation. // Checks if timing is ok (must be ascending) and if all handlers were found. auto slotIt = slotList.begin(); uint32_t count = 0; diff --git a/devicehandlers/FixedSlotSequence.h b/devicehandlers/FixedSlotSequence.h index 813d2fce..cad7ee87 100644 --- a/devicehandlers/FixedSlotSequence.h +++ b/devicehandlers/FixedSlotSequence.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -23,7 +24,6 @@ using SlotListIter = std::multiset::iterator; class FixedSlotSequence { public: - /** * @brief The constructor of the FixedSlotSequence object. * @@ -127,6 +127,8 @@ protected: SlotList slotList; uint32_t slotLengthMs; + + bool isEmpty = false; }; #endif /* FIXEDSLOTSEQUENCE_H_ */ diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index b1c97420..db0247a4 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -112,7 +112,6 @@ void FixedTimeslotTask::taskFunctionality() { vTaskDelayUntil(&xLastWakeTime, interval); //TODO deadline missed check } - } }