mueller_stopwatch #30

Merged
muellerr merged 18 commits from KSat/fsfw:mueller_stopwatch into master 2020-07-07 12:05:04 +02:00
6 changed files with 161 additions and 13 deletions
Showing only changes of commit 2a72e94d6f - Show all commits

View File

@ -3,8 +3,11 @@
#include <stdlib.h>
#include "Timekeeper.h"
extern "C" {
#include <FreeRTOS.h>
#include <task.h>
}
//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);
}

View File

@ -1,20 +1,24 @@
#include "Timekeeper.h"
#include <FreeRTOSConfig.h>
/**
Review

Where does this header comm from?

Where does this header comm from?
Review

I don't know. TickType_t is defined in partmacro.h (includes by FreeRTOS.h, just portmacro.h did not work I think) and xGetTickCount is part of task.h .

I don't know. TickType_t is defined in partmacro.h (includes by FreeRTOS.h, just portmacro.h did not work I think) and xGetTickCount is part of task.h .
Review

I now know where it comes from: The configTICK_RATE_HZ is used and is located
inside the FreeRTOSConfig.h file. This file needs to be in the include path in any case, but compiler/indexer warnings are always annoying, so I included it explicitely.

I now know where it comes from: The configTICK_RATE_HZ is used and is located inside the FreeRTOSConfig.h file. This file needs to be in the include path in any case, but compiler/indexer warnings are always annoying, so I included it explicitely.
* @file Timekeeper.cpp
* @date
*/
Timekeeper::Timekeeper() :
offset( { 0, 0 }) {
// TODO Auto-generated constructor stub
#include <framework/osal/FreeRTOS/Timekeeper.h>
extern "C" {
#include <task.h>
}
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();
}

View File

@ -2,8 +2,10 @@
#define FRAMEWORK_OSAL_FREERTOS_TIMEKEEPER_H_
#include <framework/timemanager/Clock.h>
extern "C" {
#include <FreeRTOS.h>
}
/**
* 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);

View File

@ -7,7 +7,8 @@
#include <framework/ipc/MutexFactory.h>
#include <framework/globalfunctions/timevalOperations.h>
typedef uint32_t millis_t;

Where are does types used?

Where are does types used?

stopwatch. could also be used somewhere else, is more explicit in my opinion. maybe also use it instead of uint32_t for all milliseconds related stuff?

stopwatch. could also be used somewhere else, is more explicit in my opinion. maybe also use it instead of uint32_t for all milliseconds related stuff?

Hm I think we should stick with timeval and the types defined there. Someday this might be replaced by timespec and uint32_t will be to small anyway.

Hm I think we should stick with timeval and the types defined there. Someday this might be replaced by timespec and uint32_t will be to small anyway.
typedef float seconds_t;

Seconds are converted to double in timevalOperations::toDouble(elapsedTime), this would not fit to the float type.

Seconds are converted to double in timevalOperations::toDouble(elapsedTime), this would not fit to the float type.

second is double now

second is double now

I still don't think that those typedefs are a good idea. Maybe we should stick to the types timeval or timespec uses or even use the types C++11 uses in duration Link.

I still don't think that those typedefs are a good idea. Maybe we should stick to the types timeval or timespec uses or even use the types C++11 uses in duration [Link](https://www.cplusplus.com/reference/chrono/duration/).

Hmmm.. it just makes it a bit mor explicit. I guess you mean for example time_t ?

These typedefs were inteded to explicitely be used everywhere uint32_t is used to pass around millisecond values.

The new C++ types are a bit more complicated but the clock library will become more powerful soon anyway. I started to play around with the chrono library.
Maybe continue using uint32_t for now?

Hmmm.. it just makes it a bit mor explicit. I guess you mean for example time_t ? These typedefs were inteded to explicitely be used everywhere uint32_t is used to pass around millisecond values. The new C++ types are a bit more complicated but the clock library will become more powerful soon anyway. I started to play around with the chrono library. Maybe continue using uint32_t for now?

instead of writing something like uint32_t lockTimeout, I could write millis_t lockTimeout for example

instead of writing something like uint32_t lockTimeout, I could write millis_t lockTimeout for example
class Clock {
public:

61
timemanager/Stopwatch.cpp Normal file
View File

@ -0,0 +1,61 @@
/**
* @file Stopwatch.cpp
*
* @date 08.04.2020
*/
#include <framework/timemanager/Stopwatch.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <iomanip>
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() {
Review

Here a float is returned but a double is calculated.

Here a float is returned but a double is calculated.
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;
}

71
timemanager/Stopwatch.h Normal file
View File

@ -0,0 +1,71 @@
/**
* @file Stopwatch.h
*
* @date 08.04.2020
*/
#ifndef FRAMEWORK_TIMEMANAGER_STOPWATCH_H_
#define FRAMEWORK_TIMEMANAGER_STOPWATCH_H_
#include <framework/timemanager/Clock.h>
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.
Review

The last part of the comment is outdated

The last part of the comment is outdated
*/
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_ */