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: https://github.com/InfiniTimeOrg/InfiniSim/issues/17
This commit is contained in:
parent
d6cc748ea1
commit
3cc6e74ea1
|
@ -8,7 +8,7 @@ uint32_t timer_callback_wrapper(uint32_t interval, void *param) {
|
||||||
}
|
}
|
||||||
xTimer->pxCallbackFunction(*xTimer);
|
xTimer->pxCallbackFunction(*xTimer);
|
||||||
if (xTimer->auto_reload) {
|
if (xTimer->auto_reload) {
|
||||||
return xTimer->xTimerPeriodInTicks;
|
return xTimer->timer_period_in_ms;
|
||||||
}
|
}
|
||||||
xTimer->running = false;
|
xTimer->running = false;
|
||||||
return 0; // cancel timer
|
return 0; // cancel timer
|
||||||
|
@ -28,7 +28,7 @@ TimerHandle_t xTimerCreate(const char * const pcTimerName, /*lint !e971 Unqualif
|
||||||
TimerCallbackFunction_t pxCallbackFunction)
|
TimerCallbackFunction_t pxCallbackFunction)
|
||||||
{
|
{
|
||||||
TimerHandle_t xTimer;
|
TimerHandle_t xTimer;
|
||||||
xTimer.xTimerPeriodInTicks = xTimerPeriodInTicks;
|
xTimer.timer_period_in_ms = pdTICKS_TO_MS(xTimerPeriodInTicks);
|
||||||
xTimer.auto_reload = uxAutoReload == pdTRUE;
|
xTimer.auto_reload = uxAutoReload == pdTRUE;
|
||||||
xTimer.timer_name = pcTimerName;
|
xTimer.timer_name = pcTimerName;
|
||||||
xTimer.pvTimerID = pvTimerID;
|
xTimer.pvTimerID = pvTimerID;
|
||||||
|
@ -38,7 +38,8 @@ TimerHandle_t xTimerCreate(const char * const pcTimerName, /*lint !e971 Unqualif
|
||||||
|
|
||||||
bool xTimerStart(TimerHandle_t &xTimer, TickType_t xTicksToWait) {
|
bool xTimerStart(TimerHandle_t &xTimer, TickType_t xTicksToWait) {
|
||||||
xTimer.running = true;
|
xTimer.running = true;
|
||||||
xTimer.timer_id = SDL_AddTimer(xTimer.xTimerPeriodInTicks, timer_callback_wrapper, &xTimer);
|
xTimer.expiry_time = xTaskGetTickCount() + pdMS_TO_TICKS(xTimer.timer_period_in_ms);
|
||||||
|
xTimer.timer_id = SDL_AddTimer(xTimer.timer_period_in_ms, timer_callback_wrapper, &xTimer);
|
||||||
if (xTimer.pxCallbackFunction == nullptr) {
|
if (xTimer.pxCallbackFunction == nullptr) {
|
||||||
throw std::runtime_error("xTimerStart called before xTimerCreate");
|
throw std::runtime_error("xTimerStart called before xTimerCreate");
|
||||||
}
|
}
|
||||||
|
@ -48,10 +49,10 @@ bool xTimerStart(TimerHandle_t &xTimer, TickType_t xTicksToWait) {
|
||||||
bool xTimerChangePeriod(TimerHandle_t &xTimer, TickType_t xNewPeriod, TickType_t xTicksToWait) {
|
bool xTimerChangePeriod(TimerHandle_t &xTimer, TickType_t xNewPeriod, TickType_t xTicksToWait) {
|
||||||
if (xTimer.running) {
|
if (xTimer.running) {
|
||||||
xTimerStop(xTimer, xTicksToWait);
|
xTimerStop(xTimer, xTicksToWait);
|
||||||
xTimer.xTimerPeriodInTicks = xNewPeriod;
|
xTimer.timer_period_in_ms = pdTICKS_TO_MS(xNewPeriod);
|
||||||
xTimerStart(xTimer, xTicksToWait);
|
xTimerStart(xTimer, xTicksToWait);
|
||||||
} else {
|
} else {
|
||||||
xTimer.xTimerPeriodInTicks = xNewPeriod;
|
xTimer.timer_period_in_ms = pdTICKS_TO_MS(xNewPeriod);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -67,3 +68,12 @@ bool xTimerStop(TimerHandle_t &xTimer, TickType_t xTicksToWait) {
|
||||||
xTimer.running = false;
|
xTimer.running = false;
|
||||||
return SDL_RemoveTimer(xTimer.timer_id);
|
return SDL_RemoveTimer(xTimer.timer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )
|
||||||
|
{
|
||||||
|
return xTimer.expiry_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) {
|
||||||
|
return xTimer.running;
|
||||||
|
}
|
||||||
|
|
64
sim/timers.h
64
sim/timers.h
|
@ -29,6 +29,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "portmacro_cmsis.h" // TickType_t
|
#include "portmacro_cmsis.h" // TickType_t
|
||||||
|
#include "task.h" // configTICK_RATE_HZ
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
@ -46,15 +47,20 @@ struct TimerHandle_t {
|
||||||
bool running = false;
|
bool running = false;
|
||||||
bool auto_reload = false;
|
bool auto_reload = false;
|
||||||
SDL_TimerID timer_id = 0;
|
SDL_TimerID timer_id = 0;
|
||||||
TickType_t xTimerPeriodInTicks;
|
TickType_t timer_period_in_ms;
|
||||||
|
TickType_t expiry_time;
|
||||||
std::string timer_name;
|
std::string timer_name;
|
||||||
void * pvTimerID;
|
void * pvTimerID;
|
||||||
TimerCallbackFunction_t pxCallbackFunction;
|
TimerCallbackFunction_t pxCallbackFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
constexpr uint32_t pdMS_TO_TICKS(uint32_t ticks) {
|
constexpr uint32_t pdMS_TO_TICKS(uint32_t pdMS) {
|
||||||
return ticks;
|
return pdMS * configTICK_RATE_HZ / 1000;
|
||||||
|
}
|
||||||
|
// function only available in Simulator
|
||||||
|
constexpr uint32_t pdTICKS_TO_MS(uint32_t ticks) {
|
||||||
|
return ticks * 1000 / configTICK_RATE_HZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -148,3 +154,55 @@ bool xTimerChangePeriod(TimerHandle_t &xTimer, TickType_t xNewPeriod, TickType_t
|
||||||
bool xTimerReset(TimerHandle_t &xTimer, TickType_t xTicksToWait);
|
bool xTimerReset(TimerHandle_t &xTimer, TickType_t xTicksToWait);
|
||||||
|
|
||||||
bool xTimerStop(TimerHandle_t &xTimer, TickType_t xTicksToWait);
|
bool xTimerStop(TimerHandle_t &xTimer, TickType_t xTicksToWait);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer );
|
||||||
|
*
|
||||||
|
* Returns the time in ticks at which the timer will expire. If this is less
|
||||||
|
* than the current tick count then the expiry time has overflowed from the
|
||||||
|
* current time.
|
||||||
|
*
|
||||||
|
* @param xTimer The handle of the timer being queried.
|
||||||
|
*
|
||||||
|
* @return If the timer is running then the time in ticks at which the timer
|
||||||
|
* will next expire is returned. If the timer is not running then the return
|
||||||
|
* value is undefined.
|
||||||
|
*/
|
||||||
|
TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer );
|
||||||
|
*
|
||||||
|
* Queries a timer to see if it is active or dormant.
|
||||||
|
*
|
||||||
|
* A timer will be dormant if:
|
||||||
|
* 1) It has been created but not started, or
|
||||||
|
* 2) It is an expired one-shot timer that has not been restarted.
|
||||||
|
*
|
||||||
|
* Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
|
||||||
|
* xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
|
||||||
|
* xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the
|
||||||
|
* active state.
|
||||||
|
*
|
||||||
|
* @param xTimer The timer being queried.
|
||||||
|
*
|
||||||
|
* @return pdFALSE will be returned if the timer is dormant. A value other than
|
||||||
|
* pdFALSE will be returned if the timer is active.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @verbatim
|
||||||
|
* // This function assumes xTimer has already been created.
|
||||||
|
* void vAFunction( TimerHandle_t xTimer )
|
||||||
|
* {
|
||||||
|
* if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )"
|
||||||
|
* {
|
||||||
|
* // xTimer is active, do something.
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* {
|
||||||
|
* // xTimer is not active, do something else.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endverbatim
|
||||||
|
*/
|
||||||
|
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer );
|
||||||
|
|
Loading…
Reference in New Issue
Block a user