Skip to content

Commit 3cc6e74

Browse files
committed
sim/timers: implement xTimerGetExpiryTime, xTimerIsActive, more accurate
Implement the missing functions `xTimerGetExpiryTime()` and `xTimerIsActive()` for the move of `TimerController` to use FreeRTOS timers. In the process also fix a slight inaccuracy in the ms to ticks conversion (no conversion was done as 1000 was close enough to 1024 for a first working implementation). Fixes: #17
1 parent d6cc748 commit 3cc6e74

2 files changed

Lines changed: 76 additions & 8 deletions

File tree

sim/timers.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ uint32_t timer_callback_wrapper(uint32_t interval, void *param) {
88
}
99
xTimer->pxCallbackFunction(*xTimer);
1010
if (xTimer->auto_reload) {
11-
return xTimer->xTimerPeriodInTicks;
11+
return xTimer->timer_period_in_ms;
1212
}
1313
xTimer->running = false;
1414
return 0; // cancel timer
@@ -28,7 +28,7 @@ TimerHandle_t xTimerCreate(const char * const pcTimerName, /*lint !e971 Unqualif
2828
TimerCallbackFunction_t pxCallbackFunction)
2929
{
3030
TimerHandle_t xTimer;
31-
xTimer.xTimerPeriodInTicks = xTimerPeriodInTicks;
31+
xTimer.timer_period_in_ms = pdTICKS_TO_MS(xTimerPeriodInTicks);
3232
xTimer.auto_reload = uxAutoReload == pdTRUE;
3333
xTimer.timer_name = pcTimerName;
3434
xTimer.pvTimerID = pvTimerID;
@@ -38,7 +38,8 @@ TimerHandle_t xTimerCreate(const char * const pcTimerName, /*lint !e971 Unqualif
3838

3939
bool xTimerStart(TimerHandle_t &xTimer, TickType_t xTicksToWait) {
4040
xTimer.running = true;
41-
xTimer.timer_id = SDL_AddTimer(xTimer.xTimerPeriodInTicks, timer_callback_wrapper, &xTimer);
41+
xTimer.expiry_time = xTaskGetTickCount() + pdMS_TO_TICKS(xTimer.timer_period_in_ms);
42+
xTimer.timer_id = SDL_AddTimer(xTimer.timer_period_in_ms, timer_callback_wrapper, &xTimer);
4243
if (xTimer.pxCallbackFunction == nullptr) {
4344
throw std::runtime_error("xTimerStart called before xTimerCreate");
4445
}
@@ -48,10 +49,10 @@ bool xTimerStart(TimerHandle_t &xTimer, TickType_t xTicksToWait) {
4849
bool xTimerChangePeriod(TimerHandle_t &xTimer, TickType_t xNewPeriod, TickType_t xTicksToWait) {
4950
if (xTimer.running) {
5051
xTimerStop(xTimer, xTicksToWait);
51-
xTimer.xTimerPeriodInTicks = xNewPeriod;
52+
xTimer.timer_period_in_ms = pdTICKS_TO_MS(xNewPeriod);
5253
xTimerStart(xTimer, xTicksToWait);
5354
} else {
54-
xTimer.xTimerPeriodInTicks = xNewPeriod;
55+
xTimer.timer_period_in_ms = pdTICKS_TO_MS(xNewPeriod);
5556
}
5657
return true;
5758
}
@@ -67,3 +68,12 @@ bool xTimerStop(TimerHandle_t &xTimer, TickType_t xTicksToWait) {
6768
xTimer.running = false;
6869
return SDL_RemoveTimer(xTimer.timer_id);
6970
}
71+
72+
TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )
73+
{
74+
return xTimer.expiry_time;
75+
}
76+
77+
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) {
78+
return xTimer.running;
79+
}

sim/timers.h

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#pragma once
3030

3131
#include "portmacro_cmsis.h" // TickType_t
32+
#include "task.h" // configTICK_RATE_HZ
3233

3334
#include <SDL2/SDL.h>
3435

@@ -46,15 +47,20 @@ struct TimerHandle_t {
4647
bool running = false;
4748
bool auto_reload = false;
4849
SDL_TimerID timer_id = 0;
49-
TickType_t xTimerPeriodInTicks;
50+
TickType_t timer_period_in_ms;
51+
TickType_t expiry_time;
5052
std::string timer_name;
5153
void * pvTimerID;
5254
TimerCallbackFunction_t pxCallbackFunction;
5355
};
5456

5557

56-
constexpr uint32_t pdMS_TO_TICKS(uint32_t ticks) {
57-
return ticks;
58+
constexpr uint32_t pdMS_TO_TICKS(uint32_t pdMS) {
59+
return pdMS * configTICK_RATE_HZ / 1000;
60+
}
61+
// function only available in Simulator
62+
constexpr uint32_t pdTICKS_TO_MS(uint32_t ticks) {
63+
return ticks * 1000 / configTICK_RATE_HZ;
5864
}
5965

6066
/**
@@ -148,3 +154,55 @@ bool xTimerChangePeriod(TimerHandle_t &xTimer, TickType_t xNewPeriod, TickType_t
148154
bool xTimerReset(TimerHandle_t &xTimer, TickType_t xTicksToWait);
149155

150156
bool xTimerStop(TimerHandle_t &xTimer, TickType_t xTicksToWait);
157+
158+
/**
159+
* TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer );
160+
*
161+
* Returns the time in ticks at which the timer will expire. If this is less
162+
* than the current tick count then the expiry time has overflowed from the
163+
* current time.
164+
*
165+
* @param xTimer The handle of the timer being queried.
166+
*
167+
* @return If the timer is running then the time in ticks at which the timer
168+
* will next expire is returned. If the timer is not running then the return
169+
* value is undefined.
170+
*/
171+
TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer );
172+
173+
/**
174+
* BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer );
175+
*
176+
* Queries a timer to see if it is active or dormant.
177+
*
178+
* A timer will be dormant if:
179+
* 1) It has been created but not started, or
180+
* 2) It is an expired one-shot timer that has not been restarted.
181+
*
182+
* Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
183+
* xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
184+
* xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the
185+
* active state.
186+
*
187+
* @param xTimer The timer being queried.
188+
*
189+
* @return pdFALSE will be returned if the timer is dormant. A value other than
190+
* pdFALSE will be returned if the timer is active.
191+
*
192+
* Example usage:
193+
* @verbatim
194+
* // This function assumes xTimer has already been created.
195+
* void vAFunction( TimerHandle_t xTimer )
196+
* {
197+
* if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )"
198+
* {
199+
* // xTimer is active, do something.
200+
* }
201+
* else
202+
* {
203+
* // xTimer is not active, do something else.
204+
* }
205+
* }
206+
* @endverbatim
207+
*/
208+
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer );

0 commit comments

Comments
 (0)