fix: do not mix an epoch offset into the FreeRTOS monotonic clock

getClockMonotonic added monotonicClockOffset on top of the uptime. That
offset is indeterminate until the first setClock call and jumps when it is
latched, so every Countdown and Stopwatch armed before that point either
expires immediately or measures against garbage.

The monotonicity came from the uptime alone, the offset only made the value
look epoch based. The Linux and host implementations return
CLOCK_MONOTONIC_RAW with no offset, so this also makes the OSALs agree.

All users take differences only: Countdown, Stopwatch and PeriodicHelper.

Also drops the Clock statics monotonicClockInitialized and
monotonicClockOffset, which were declared but never defined or used.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Tobias Baumgartl
2026-09-24 22:48:16 +02:00
co-authored by Claude Opus 5
parent 42ecc7caf1
commit f0e7e8b523
4 changed files with 4 additions and 18 deletions
+3 -1
View File
@@ -48,7 +48,9 @@ ReturnValue_t Clock::getClock(timeval* time) {
}
ReturnValue_t Clock::getClockMonotonic(timeval* time) {
*time = Timekeeper::instance()->getMonotonicClockOffset() + getUptime();
// Ticks since scheduler start, with no epoch offset on top. Same contract as the Linux and
// host implementations, which return CLOCK_MONOTONIC_RAW: only differences are meaningful.
*time = getUptime();
return returnvalue::OK;
}
+1 -9
View File
@@ -17,13 +17,7 @@ Timekeeper* Timekeeper::instance() {
return myinstance;
}
void Timekeeper::setOffset(const timeval& offset) {
if (not monotonicClockInitialized) {
this->monotonicClockOffset = offset;
monotonicClockInitialized = true;
}
this->offset = offset;
}
void Timekeeper::setOffset(const timeval& offset) { this->offset = offset; }
timeval Timekeeper::ticksToTimeval(TickType_t ticks) {
timeval uptime;
@@ -39,5 +33,3 @@ timeval Timekeeper::ticksToTimeval(TickType_t ticks) {
}
TickType_t Timekeeper::getTicks() { return xTaskGetTickCount(); }
const timeval Timekeeper::getMonotonicClockOffset() const { return monotonicClockOffset; }
-6
View File
@@ -18,14 +18,9 @@ class Timekeeper {
Timekeeper();
timeval offset;
// Set when offset is initialized the first time
timeval monotonicClockOffset;
bool monotonicClockInitialized = false;
static Timekeeper* myinstance;
void setMonotonicClockOffset(const timeval& monotonicClockOffset);
public:
static Timekeeper* instance();
virtual ~Timekeeper();
@@ -39,7 +34,6 @@ class Timekeeper {
const timeval& getOffset() const;
void setOffset(const timeval& offset);
const timeval getMonotonicClockOffset() const;
};
#endif /* FRAMEWORK_OSAL_FREERTOS_TIMEKEEPER_H_ */
-2
View File
@@ -192,8 +192,6 @@ class Clock {
static MutexIF *timeMutex;
static uint16_t leapSeconds;
static bool leapSecondsSet;
static bool monotonicClockInitialized;
static timeval monotonicClockOffset;
};
#endif /* FSFW_TIMEMANAGER_CLOCK_H_ */