Merge pull request 'new monotonic clock API' (#128) from feature_monotonic_clock_api into develop
Reviewed-on: #128 Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
This commit is contained in:
commit
2c5af91db1
@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
|
|
||||||
|
- Add monotonic watchdog Clock API and use it in `Countdown` and `Stopwatch` class.
|
||||||
- Bugfix in `Service11TelecommandScheduling` which allowed commands
|
- Bugfix in `Service11TelecommandScheduling` which allowed commands
|
||||||
time tagged in the past to be inserted.
|
time tagged in the past to be inserted.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/738
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/738
|
||||||
|
@ -47,7 +47,32 @@ ReturnValue_t Clock::setClock(const timeval* time) {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
ReturnValue_t Clock::getClockMonotonic(timeval* time) {
|
||||||
|
#if defined(PLATFORM_WIN)
|
||||||
|
// TODO: Implement with std::chrono::steady_clock.. or in some other way. I am not even sure
|
||||||
|
// whether this is possible with steady_clock. The conversion we have to do here just to be
|
||||||
|
// generic is kind of awkward..
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
#elif defined(PLATFORM_UNIX)
|
||||||
|
timespec timeMonotonic;
|
||||||
|
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic);
|
||||||
|
if (status != 0) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
time->tv_sec = timeMonotonic.tv_sec;
|
||||||
|
time->tv_usec = timeMonotonic.tv_nsec / 1000.0;
|
||||||
|
return returnvalue::OK;
|
||||||
|
#else
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("Clock::getUptime: Not implemented for found OS!\n");
|
||||||
|
#endif
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Clock::getClock(timeval* time) {
|
||||||
#if defined(PLATFORM_WIN)
|
#if defined(PLATFORM_WIN)
|
||||||
auto now = std::chrono::system_clock::now();
|
auto now = std::chrono::system_clock::now();
|
||||||
auto secondsChrono = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
auto secondsChrono = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
||||||
@ -75,6 +100,10 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||||
|
return Clock::getClock(time);
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||||
if (time == nullptr) {
|
if (time == nullptr) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
|
@ -42,7 +42,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
ReturnValue_t Clock::getClock(timeval *time) {
|
||||||
timespec timeUnix{};
|
timespec timeUnix{};
|
||||||
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
|
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
@ -53,6 +53,10 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||||
|
return Clock::getClock(time);
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||||
timeval timeVal{};
|
timeval timeVal{};
|
||||||
ReturnValue_t result = getClock_timeval(&timeVal);
|
ReturnValue_t result = getClock_timeval(&timeVal);
|
||||||
@ -64,6 +68,17 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Clock::getClockMonotonic(timeval *time) {
|
||||||
|
timespec timeMonotonic{};
|
||||||
|
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic);
|
||||||
|
if (status != 0) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
time->tv_sec = timeMonotonic.tv_sec;
|
||||||
|
time->tv_usec = timeMonotonic.tv_nsec / 1000.0;
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
timeval Clock::getUptime() {
|
timeval Clock::getUptime() {
|
||||||
timeval uptime{};
|
timeval uptime{};
|
||||||
auto result = getUptime(&uptime);
|
auto result = getUptime(&uptime);
|
||||||
|
@ -49,6 +49,13 @@ class Clock {
|
|||||||
* @return -@c returnvalue::OK on success. Otherwise, the OS failure code is returned.
|
* @return -@c returnvalue::OK on success. Otherwise, the OS failure code is returned.
|
||||||
*/
|
*/
|
||||||
static ReturnValue_t setClock(const timeval *time);
|
static ReturnValue_t setClock(const timeval *time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use getClock instead, which does the same.
|
||||||
|
* @param time
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static ReturnValue_t getClock_timeval(timeval *time);
|
||||||
/**
|
/**
|
||||||
* This system call returns the current system clock in timeval format.
|
* This system call returns the current system clock in timeval format.
|
||||||
* The timval format has the fields @c tv_sec with seconds and @c tv_usec with
|
* The timval format has the fields @c tv_sec with seconds and @c tv_usec with
|
||||||
@ -56,7 +63,18 @@ class Clock {
|
|||||||
* @param time A pointer to a timeval struct where the current time is stored.
|
* @param time A pointer to a timeval struct where the current time is stored.
|
||||||
* @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned.
|
* @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned.
|
||||||
*/
|
*/
|
||||||
static ReturnValue_t getClock_timeval(timeval *time);
|
static ReturnValue_t getClock(timeval *time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a monotonic clock. This clock this is also more suited for measuring elapsed times
|
||||||
|
* between two time points, but less suited when the absolute time is required.
|
||||||
|
*
|
||||||
|
* Implementation example: A generic UNIX implementation can use CLOCK_MONOTONIC_RAW with
|
||||||
|
* `clock_gettime`.
|
||||||
|
* @param time
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static ReturnValue_t getClockMonotonic(timeval *time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the time since boot in a timeval struct
|
* Get the time since boot in a timeval struct
|
||||||
|
@ -16,7 +16,7 @@ Countdown::~Countdown() = default;
|
|||||||
ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) {
|
ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) {
|
||||||
timeout.tv_sec = milliseconds / 1000;
|
timeout.tv_sec = milliseconds / 1000;
|
||||||
timeout.tv_usec = (milliseconds % 1000) * 1000;
|
timeout.tv_usec = (milliseconds % 1000) * 1000;
|
||||||
return Clock::getClock_timeval(&startTime);
|
return Clock::getClockMonotonic(&startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Countdown::hasTimedOut() const {
|
bool Countdown::hasTimedOut() const {
|
||||||
@ -48,7 +48,7 @@ uint32_t Countdown::timevalToMs(timeval &tv) { return tv.tv_sec * 1000 + tv.tv_u
|
|||||||
|
|
||||||
ReturnValue_t Countdown::setTimeoutTv(timeval tv) {
|
ReturnValue_t Countdown::setTimeoutTv(timeval tv) {
|
||||||
timeout = tv;
|
timeout = tv;
|
||||||
return Clock::getClock_timeval(&startTime);
|
return Clock::getClockMonotonic(&startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Countdown::getTimeoutMs() const { return timeout.tv_sec * 1000 + timeout.tv_usec / 1000; }
|
uint32_t Countdown::getTimeoutMs() const { return timeout.tv_sec * 1000 + timeout.tv_usec / 1000; }
|
||||||
@ -57,6 +57,6 @@ timeval Countdown::getTimeout() const { return timeout; }
|
|||||||
|
|
||||||
timeval Countdown::getCurrentTime() const {
|
timeval Countdown::getCurrentTime() const {
|
||||||
timeval currentTime{};
|
timeval currentTime{};
|
||||||
Clock::getClock_timeval(¤tTime);
|
Clock::getClockMonotonic(¤tTime);
|
||||||
return currentTime;
|
return currentTime;
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode)
|
Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode)
|
||||||
: displayOnDestruction(displayOnDestruction), displayMode(displayMode) {
|
: displayOnDestruction(displayOnDestruction), displayMode(displayMode) {
|
||||||
// Measures start time on initialization.
|
// Measures start time on initialization.
|
||||||
Clock::getClock_timeval(&startTime);
|
Clock::getClockMonotonic(&startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stopwatch::start() { Clock::getUptime(&startTime); }
|
void Stopwatch::start() { Clock::getClockMonotonic(&startTime); }
|
||||||
|
|
||||||
dur_millis_t Stopwatch::stop(bool display) {
|
dur_millis_t Stopwatch::stop(bool display) {
|
||||||
stopInternal();
|
stopInternal();
|
||||||
@ -63,6 +63,6 @@ StopwatchDisplayMode Stopwatch::getDisplayMode() const { return displayMode; }
|
|||||||
|
|
||||||
void Stopwatch::stopInternal() {
|
void Stopwatch::stopInternal() {
|
||||||
timeval endTime;
|
timeval endTime;
|
||||||
Clock::getClock_timeval(&endTime);
|
Clock::getClockMonotonic(&endTime);
|
||||||
elapsedTime = endTime - startTime;
|
elapsedTime = endTime - startTime;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user