diff --git a/datalinklayer/Clcw.cpp b/datalinklayer/Clcw.cpp index 448d4d7bc..0ffa7abf6 100644 --- a/datalinklayer/Clcw.cpp +++ b/datalinklayer/Clcw.cpp @@ -55,7 +55,8 @@ void Clcw::setBitLock(bool bitLock) { } void Clcw::print() { - debug << "Clcw::print: Clcw is: " << std::hex << getAsWhole() << std::dec << std::endl; + debug << "Clcw::print: Clcw is: " << std::hex << getAsWhole() + << std::dec << std::endl; } void Clcw::setWhole(uint32_t rawClcw) { diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index e5d4ffdef..655b467a0 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -60,7 +60,8 @@ uint8_t PoolEntry::getValid() { template void PoolEntry::print() { for (uint8_t size = 0; size < this->length; size++ ) { - debug << "| " << std::hex << (double)this->address[size] << (this->valid? " (valid) " : " (invalid) "); + debug << "| " << std::hex << (double)this->address[size] + << (this->valid? " (valid) " : " (invalid) "); } debug << std::dec << std::endl; } diff --git a/health/HealthHelper.cpp b/health/HealthHelper.cpp index 8fc413edd..931645d1a 100644 --- a/health/HealthHelper.cpp +++ b/health/HealthHelper.cpp @@ -89,8 +89,7 @@ void HealthHelper::handleSetHealthCommand(CommandMessage* message) { } if (MessageQueueSenderIF::sendMessage(message->getSender(), &reply, owner->getCommandQueue()) != HasReturnvaluesIF::RETURN_OK) { - debug - << "HealthHelper::handleHealthCommand: sending health reply failed." - << std::endl; + debug << "HealthHelper::handleHealthCommand: sending health " + "reply failed." << std::endl; } } diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index 546c5a46d..05c97ae2e 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -21,26 +21,68 @@ BinarySemaphore::~BinarySemaphore() { vSemaphoreDelete(handle); } +// This copy ctor is important as it prevents the assignment to a ressource +// (other.handle) variable which is later deleted! +BinarySemaphore::BinarySemaphore(const BinarySemaphore& other) { + xSemaphoreCreateBinary(handle); + if(handle == nullptr) { + error << "Binary semaphore creation failure" << std::endl; + } +} + +BinarySemaphore& BinarySemaphore::operator =(const BinarySemaphore& s) { + if(this != &s) { + xSemaphoreCreateBinary(handle); + if(handle == nullptr) { + error << "Binary semaphore creation failure" << std::endl; + } + } + return *this; +} + +BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { + xSemaphoreCreateBinary(handle); + if(handle == nullptr) { + error << "Binary semaphore creation failure" << std::endl; + } +} + +BinarySemaphore& BinarySemaphore::operator =( + BinarySemaphore&& s) { + if(&s != this) { + xSemaphoreCreateBinary(handle); + if(handle == nullptr) { + error << "Binary semaphore creation failure" << std::endl; + } + } + return *this; +} + ReturnValue_t BinarySemaphore::takeBinarySemaphore(uint32_t timeoutMs) { if(handle == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return SEMAPHORE_NULLPOINTER; } - TickType_t timeout = portMAX_DELAY; - if(timeoutMs != 0) { - timeout = pdMS_TO_TICKS(timeoutMs); + TickType_t timeout = BinarySemaphore::NO_BLOCK_TICKS; + if(timeoutMs == BinarySemaphore::BLOCK_TIMEOUT) { + timeout = BinarySemaphore::BLOCK_TIMEOUT_TICKS; + } + else if(timeoutMs > BinarySemaphore::NO_BLOCK_TIMEOUT){ + timeout = pdMS_TO_TICKS(timeoutMs); } BaseType_t returncode = xSemaphoreTake(handle, timeout); if (returncode == pdPASS) { return HasReturnvaluesIF::RETURN_OK; - } else { - return SEMAPHORE_NOT_FOUND; + } + else { + return SEMAPHORE_TIMEOUT; } } -ReturnValue_t BinarySemaphore::takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks) { +ReturnValue_t BinarySemaphore::takeBinarySemaphoreTickTimeout( + TickType_t timeoutTicks) { if(handle == nullptr) { - return SEMAPHORE_NOT_FOUND; + return SEMAPHORE_NULLPOINTER; } BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks); @@ -53,7 +95,7 @@ ReturnValue_t BinarySemaphore::takeBinarySemaphoreTickTimeout(TickType_t timeout ReturnValue_t BinarySemaphore::giveBinarySemaphore() { if (handle == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return SEMAPHORE_NULLPOINTER; } BaseType_t returncode = xSemaphoreGive(handle); if (returncode == pdPASS) { @@ -69,7 +111,7 @@ SemaphoreHandle_t BinarySemaphore::getSemaphore() { ReturnValue_t BinarySemaphore::giveBinarySemaphore(SemaphoreHandle_t semaphore) { if (semaphore == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return SEMAPHORE_NULLPOINTER; } BaseType_t returncode = xSemaphoreGive(semaphore); if (returncode == pdPASS) { @@ -86,11 +128,12 @@ void BinarySemaphore::resetSemaphore() { } } + // Be careful with the stack size here. This is called from an ISR! ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken) { if (semaphore == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return SEMAPHORE_NULLPOINTER; } BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, higherPriorityTaskWoken); if (returncode == pdPASS) { @@ -99,11 +142,10 @@ ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t sema // TODO: I don't know if this will ever happen but if it does, // I want to to know in case this causes issues. If it doesn't // we should remove this. - TRACE_INFO("Binary Semaphore: Higher priority task unblocked!"); TaskManagement::requestContextSwitch(CallContext::isr); } return HasReturnvaluesIF::RETURN_OK; } else { - return HasReturnvaluesIF::RETURN_FAILED; + return SEMAPHORE_NOT_OWNED; } } diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index a809f0bb1..541266929 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -20,22 +20,51 @@ class BinarySemaphore: public HasReturnvaluesIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - /** Semaphore object not found */ - static const ReturnValue_t SEMAPHORE_NOT_FOUND = MAKE_RETURN_CODE(1); - /** Semaphore timeout */ - static const ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(2); + //! No block time, poll the semaphore. Can also be used as tick type. + //! Can be passed as tick type and ms value. + static constexpr uint32_t NO_BLOCK_TIMEOUT = 0; + static constexpr TickType_t NO_BLOCK_TICKS = 0; + //! No block time, poll the semaphore. + //! Can be passed as tick type and ms value. + static constexpr TickType_t BLOCK_TIMEOUT_TICKS = portMAX_DELAY; + static constexpr uint32_t BLOCK_TIMEOUT = portMAX_DELAY; + + //! Semaphore timeout + static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1); /** The current semaphore can not be given, because it is not owned */ - static const ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(3); + static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2); + static constexpr ReturnValue_t SEMAPHORE_NULLPOINTER = MAKE_RETURN_CODE(3); /** * Create a binary semaphore */ BinarySemaphore(); + /** + * Copy ctor + * @param + */ + BinarySemaphore(const BinarySemaphore&); + + /** + * Copy assignment + */ + BinarySemaphore& operator=(const BinarySemaphore&); + + /** + * Move constructor + */ + BinarySemaphore (BinarySemaphore &&); + + /** + * Move assignment + */ + BinarySemaphore & operator=(BinarySemaphore &&); + /** * Delete the binary semaphore to prevent a memory leak */ - ~BinarySemaphore(); + virtual ~BinarySemaphore(); /** * Take the binary semaphore. @@ -46,7 +75,8 @@ public: * @return -@c RETURN_OK on success * -@c RETURN_FAILED on failure */ - ReturnValue_t takeBinarySemaphore(uint32_t timeoutMs); + ReturnValue_t takeBinarySemaphore(uint32_t timeoutMs = + BinarySemaphore::NO_BLOCK_TIMEOUT); /** * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. @@ -54,7 +84,8 @@ public: * @return -@c RETURN_OK on success * -@c RETURN_FAILED on failure */ - ReturnValue_t takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks); + ReturnValue_t takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks = + BinarySemaphore::NO_BLOCK_TICKS); /** * Give back the binary semaphore @@ -96,8 +127,4 @@ private: SemaphoreHandle_t handle; }; - - - - #endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ diff --git a/osal/FreeRTOS/Clock.cpp b/osal/FreeRTOS/Clock.cpp index cffc2125e..5e597f258 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 81f7f9979..949e1df3c 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 2ba3e4a9b..05f0f7011 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/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index 32bc263ee..44cf1168f 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -7,7 +7,8 @@ #include #include -//Unfortunately, there must be a forward declaration of log_fe (MUST be defined in main), to let the system know where to write to. +//Unfortunately, there must be a forward declaration of log_fe +// (MUST be defined in main), to let the system know where to write to. extern std::ostream debug; extern std::ostream info; extern std::ostream warning; diff --git a/timemanager/CCSDSTime.cpp b/timemanager/CCSDSTime.cpp index 29aafb68d..47cab911d 100644 --- a/timemanager/CCSDSTime.cpp +++ b/timemanager/CCSDSTime.cpp @@ -196,7 +196,8 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* to->usecond = (second - floor(second)) * 1000000; return RETURN_OK; } -// Warning: Compiler/Linker fails ambiguously if library does not implement C99 I/O +// Warning: Compiler/Linker fails ambiguously if library does not implement +// C99 I/O #else uint16_t year; uint8_t month; diff --git a/timemanager/Clock.h b/timemanager/Clock.h index af6572472..afa9963c5 100644 --- a/timemanager/Clock.h +++ b/timemanager/Clock.h @@ -7,7 +7,8 @@ #include #include - +typedef uint32_t ms_normal_t; +typedef double ms_double_t; class Clock { public: diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp new file mode 100644 index 000000000..37133def3 --- /dev/null +++ b/timemanager/Stopwatch.cpp @@ -0,0 +1,62 @@ +/** + * @file Stopwatch.cpp + * + * @date 08.04.2020 + */ + +#include +#include + +Stopwatch::Stopwatch(bool displayOnDestruction, DisplayMode displayMode): + displayOnDestruction(displayOnDestruction) { + Clock::getUptime(&startTime); + stopwatchState = StopwatchState::STARTED; +} + +void Stopwatch::start() { + startTime = Clock::getUptime(); +} + +ms_normal_t Stopwatch::stop() { + elapsedTime = Clock::getUptime() - startTime; + int32_t elapsedTimeMs = elapsedTime.tv_sec * 1000 + + elapsedTime.tv_usec/1000; + if(elapsedTimeMs < 0) { + error << "Stopwatch: Measured time negative!"; + return INVALID_TIME; + } + else { + return static_cast(elapsedTimeMs); + } +} + +ms_double_t Stopwatch::stopPrecise() { + elapsedTime = Clock::getUptime() - startTime; + return timevalOperations::toDouble(elapsedTime) * 1000.0; +} + + +void Stopwatch::display() { + if(displayMode == DisplayMode::MS_FLOAT) { + info << "Stopwatch: Operation took " << + elapsedTimeMs << " milliseconds" << std::endl; + } + else { + timeval elapsedTime = stopTime - startTime; + info << "Stopwatch: Operation took " << elapsedTime.tv_sec * 1000 + + elapsedTime.tv_usec * 1000 << " milliseconds"; + } +} + + +Stopwatch::~Stopwatch() { + if(displayOnDestruction) { + stopInternal(); + display(); + } +} + +void Stopwatch::stopInternal() { + elapsedTime = Clock::getUptime() - startTime; + elapsedTimeMs = timevalOperations::toDouble(elapsedTime) * 1000.0; +} diff --git a/timemanager/Stopwatch.h b/timemanager/Stopwatch.h new file mode 100644 index 000000000..6f58553f1 --- /dev/null +++ b/timemanager/Stopwatch.h @@ -0,0 +1,52 @@ +/** + * @file Stopwatch.h + * + * @date 08.04.2020 + */ + +#ifndef FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ +#define FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ +#include + +class Stopwatch { + enum class DisplayMode { + MS_FLOAT, + MS + }; + + Stopwatch(bool displayOnDestruction = true, DisplayMode displayMode = + DisplayMode::MS_FLOAT); + virtual~ Stopwatch(); + + void start(); + + ms_normal_t stop(); + ms_double_t stopPrecise(); + + void display(); +private: + static const ms_normal_t INVALID_TIME = 0xFFFFFFFF; + + timeval startTime {0, 0}; + timeval stopTime {0, 0}; + timeval elapsedTime {0, 0}; + double elapsedTimeMs = 0; + //ms_normal_t elapsedTimeMs {0}; + + bool displayOnDestruction = true; + + enum class StopwatchState { + IDLE, + STARTED, + }; + + StopwatchState stopwatchState = StopwatchState::IDLE; + DisplayMode displayMode = DisplayMode::MS_FLOAT; + + void stopInternal(); +}; + + + + +#endif /* FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ */