From 3cc6e74ea14a8d4f6ee4f5f6339f4aa8a9c05111 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Tue, 29 Mar 2022 22:41:09 +0200 Subject: [PATCH] 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 --- sim/timers.cpp | 20 ++++++++++++---- sim/timers.h | 64 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 76 insertions(+), 8 deletions(-) diff --git a/sim/timers.cpp b/sim/timers.cpp index 4a1581a..c4d6c54 100644 --- a/sim/timers.cpp +++ b/sim/timers.cpp @@ -8,7 +8,7 @@ uint32_t timer_callback_wrapper(uint32_t interval, void *param) { } xTimer->pxCallbackFunction(*xTimer); if (xTimer->auto_reload) { - return xTimer->xTimerPeriodInTicks; + return xTimer->timer_period_in_ms; } xTimer->running = false; return 0; // cancel timer @@ -28,7 +28,7 @@ TimerHandle_t xTimerCreate(const char * const pcTimerName, /*lint !e971 Unqualif TimerCallbackFunction_t pxCallbackFunction) { TimerHandle_t xTimer; - xTimer.xTimerPeriodInTicks = xTimerPeriodInTicks; + xTimer.timer_period_in_ms = pdTICKS_TO_MS(xTimerPeriodInTicks); xTimer.auto_reload = uxAutoReload == pdTRUE; xTimer.timer_name = pcTimerName; 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) { 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) { 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) { if (xTimer.running) { xTimerStop(xTimer, xTicksToWait); - xTimer.xTimerPeriodInTicks = xNewPeriod; + xTimer.timer_period_in_ms = pdTICKS_TO_MS(xNewPeriod); xTimerStart(xTimer, xTicksToWait); } else { - xTimer.xTimerPeriodInTicks = xNewPeriod; + xTimer.timer_period_in_ms = pdTICKS_TO_MS(xNewPeriod); } return true; } @@ -67,3 +68,12 @@ bool xTimerStop(TimerHandle_t &xTimer, TickType_t xTicksToWait) { xTimer.running = false; 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; +} diff --git a/sim/timers.h b/sim/timers.h index 4552567..6e22d7a 100644 --- a/sim/timers.h +++ b/sim/timers.h @@ -29,6 +29,7 @@ #pragma once #include "portmacro_cmsis.h" // TickType_t +#include "task.h" // configTICK_RATE_HZ #include @@ -46,15 +47,20 @@ struct TimerHandle_t { bool running = false; bool auto_reload = false; SDL_TimerID timer_id = 0; - TickType_t xTimerPeriodInTicks; + TickType_t timer_period_in_ms; + TickType_t expiry_time; std::string timer_name; void * pvTimerID; TimerCallbackFunction_t pxCallbackFunction; }; -constexpr uint32_t pdMS_TO_TICKS(uint32_t ticks) { - return ticks; +constexpr uint32_t pdMS_TO_TICKS(uint32_t pdMS) { + 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 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 );