#include "os/os.h" #include "os_util.h" #include "timers.h" /* TODO: what block time should be used ? */ #define OS_TIMER_WAIT_FOREVER portMAX_DELAY #define OS_TIMER_WAIT_NONE 0 /* Timer private data definition */ typedef struct OS_TimerPriv { TimerHandle_t handle; /* Timer handle */ os_timer_cb_fn callback; /* Timer expire callback function */ void *argument; /* Argument of timer expire callback function */ } OS_TimerPriv_t; static void _os_timer_cb(TimerHandle_t xTimer) { OS_TimerPriv_t *priv; priv = pvTimerGetTimerID(xTimer); if (priv && priv->callback) { priv->callback(priv->argument); } else { OS_WRN("Invalid timer callback\n"); } } os_state os_timer_create(os_timer_t *timer, os_timer_cb_fn cb, void *arg) { OS_TimerPriv_t *priv; OS_ASS_HDL(!os_timer_is_valid(timer), timer->handle); priv = os_malloc(sizeof(OS_TimerPriv_t)); if (priv == NULL) { return OS_E_NOMEM; } priv->callback = cb; priv->argument = arg; priv->handle = xTimerCreate("", os_calc_msec_to_ticks(OS_WAIT_FOREVER), pdFALSE, priv, _os_timer_cb); if (priv->handle == NULL) { OS_ERR("err %p\r\n", priv->handle); os_free(priv); return OS_FAIL; } timer->handle = priv; return OS_OK; } static TimerHandle_t _os_timer_get_handle(os_timer_t *timer) { OS_TimerPriv_t *priv = timer->handle; return priv->handle; } os_state os_timer_delete(os_timer_t *timer) { TimerHandle_t handle; int ret; OS_ASS_HDL(os_timer_is_valid(timer), timer->handle); handle = _os_timer_get_handle(timer); ret = xTimerDelete(handle, OS_TIMER_WAIT_FOREVER); if (ret != pdPASS) { OS_ERR("err %d\r\n", ret); return OS_FAIL; } OS_TimerPriv_t *priv = timer->handle; timer->handle = NULL; os_free(priv); return OS_OK; } os_state os_timer_start(os_timer_t *timer) { TimerHandle_t handle; int ret; BaseType_t taskWoken; OS_ASS_HDL(os_timer_is_valid(timer), timer->handle); handle = _os_timer_get_handle(timer); if (os_is_isr_context()) { taskWoken = pdFALSE; ret = xTimerStartFromISR(handle, &taskWoken); if (ret != pdPASS) { OS_ERR("err %d\r\n", ret); return OS_FAIL; } portYIELD_FROM_ISR(taskWoken); } else { ret = xTimerStart(handle, OS_TIMER_WAIT_NONE); if (ret != pdPASS) { OS_ERR("err %d\r\n", ret); return OS_FAIL; } } return OS_OK; } os_state os_timer_set_period(os_timer_t *timer, os_timer_type_t type, os_time_t period_ms) { TimerHandle_t handle; TickType_t ticks; int ret; OS_ASS_HDL(os_timer_is_valid(timer), timer->handle); handle = _os_timer_get_handle(timer); ticks = os_calc_msec_to_ticks(period_ms); if (os_is_isr_context()) { BaseType_t taskWoken = pdFALSE; ret = xTimerChangePeriodFromISR(handle, ticks, &taskWoken); if (ret != pdPASS) { OS_ERR("err %d\r\n", ret); return OS_FAIL; } portYIELD_FROM_ISR(taskWoken); } else { ret = xTimerChangePeriod(handle, ticks, OS_TIMER_WAIT_NONE); if (ret != pdPASS) { OS_ERR("err %d\r\n", ret); return OS_FAIL; } } vTimerSetReloadMode(handle, type == OS_TIMER_PERIODIC ? pdTRUE : pdFALSE); return OS_OK; } os_state os_timer_stop(os_timer_t *timer) { TimerHandle_t handle; int ret; BaseType_t taskWoken; OS_ASS_HDL(os_timer_is_valid(timer), timer->handle); handle = _os_timer_get_handle(timer); if (os_is_isr_context()) { taskWoken = pdFALSE; ret = xTimerStopFromISR(handle, &taskWoken); if (ret != pdPASS) { OS_ERR("err %d\r\n", ret); return OS_FAIL; } portYIELD_FROM_ISR(taskWoken); } else { ret = xTimerStop(handle, OS_TIMER_WAIT_FOREVER); if (ret != pdPASS) { OS_ERR("err %d\r\n", ret); return OS_FAIL; } } return OS_OK; } bool os_timer_is_pending(os_timer_t *timer) { TimerHandle_t handle; if (!os_timer_is_valid(timer)) { return 0; } handle = _os_timer_get_handle(timer); return (xTimerIsTimerActive(handle) != pdFALSE); } bool os_timer_is_valid(os_timer_t *timer) { if (timer && timer->handle) { return true; } else { return false; } }