diff options
author | Elieva Pignat <Elieva.Pignat@arm.com> | 2018-06-14 17:45:50 +0100 |
---|---|---|
committer | davidcunado-arm <david.cunado@arm.com> | 2018-07-25 11:35:23 +0100 |
commit | 9be0a173bade11b78fad74fd8181623eeeb096ce (patch) | |
tree | 345d88004d122276c64ccd8ebb609e14aeafb8f3 /module/timer | |
parent | a8114e3b5b55688d362d2ea862253bc8caa0ab16 (diff) |
timer: add function to get the remaining ticks of next alarm
Change-Id: I339715bf64ba38b6c1b0473419e55eed4e330e68
Signed-off-by: Elieva Pignat <Elieva.Pignat@arm.com>
Diffstat (limited to 'module/timer')
-rw-r--r-- | module/timer/include/mod_timer.h | 21 | ||||
-rw-r--r-- | module/timer/src/mod_timer.c | 70 |
2 files changed, 84 insertions, 7 deletions
diff --git a/module/timer/include/mod_timer.h b/module/timer/include/mod_timer.h index 3ba4a525..1caca802 100644 --- a/module/timer/include/mod_timer.h +++ b/module/timer/include/mod_timer.h @@ -223,6 +223,27 @@ struct mod_timer_api { int (*remaining)(fwk_id_t dev_id, uint64_t timestamp, uint64_t *remaining_ticks); + + /*! + * \brief Get the number of ticks before the next alarm trigger of a given + * timer. + * + * \warning If the timer has no active alarm, \p remaining_ticks is not + * initialized. + * + * \param dev_id Element identifier that identifies the timer device. + * \param [out] has_alarm \c true if the timer has an active alarm, + * otherwise \c false. + * \param [out] remaining_ticks Number of ticks between now and the next + * alarm trigger of the timer identified by \p dev_id. + * + * \retval FWK_SUCCESS Operation succeeded. + * \retval FWK_E_PARAM One of the parameters is invalid. + * \return One of the other specific error codes described by the framework. + */ + int (*get_next_alarm_remaining)(fwk_id_t dev_id, + bool *has_alarm, + uint64_t *remaining_ticks); }; /*! diff --git a/module/timer/src/mod_timer.c b/module/timer/src/mod_timer.c index 2b61cd26..a80e4901 100644 --- a/module/timer/src/mod_timer.c +++ b/module/timer/src/mod_timer.c @@ -11,6 +11,7 @@ #include <assert.h> #include <stdbool.h> #include <stdint.h> +#include <fwk_assert.h> #include <fwk_element.h> #include <fwk_errno.h> #include <fwk_event.h> @@ -119,6 +120,29 @@ static int _timestamp_from_now(struct dev_ctx *ctx, return FWK_SUCCESS; } +static int _remaining(const struct dev_ctx *ctx, + uint64_t timestamp, + uint64_t *remaining_ticks) +{ + int status; + uint64_t counter; + + fwk_assert(ctx != NULL); + fwk_assert(remaining_ticks != NULL); + + status = ctx->driver->get_counter(ctx->driver_dev_id, &counter); + if (!fwk_expect(status == FWK_SUCCESS)) + return status; + + /* If timestamp is in the past, remaining_ticks is set to zero. */ + if (timestamp < counter) + *remaining_ticks = 0; + else + *remaining_ticks = timestamp - counter; + + return FWK_SUCCESS; +} + static void _configure_timer_with_next_alarm(struct dev_ctx *ctx) { struct alarm_ctx *alarm_head; @@ -309,7 +333,6 @@ static int remaining(fwk_id_t dev_id, { struct dev_ctx *ctx; int status; - uint64_t counter; status = fwk_module_check_call(dev_id); if (status != FWK_SUCCESS) @@ -320,16 +343,48 @@ static int remaining(fwk_id_t dev_id, if (remaining_ticks == NULL) return FWK_E_PARAM; - status = ctx->driver->get_counter(ctx->driver_dev_id, &counter); + return _remaining(ctx, timestamp, remaining_ticks); +} + +static int get_next_alarm_remaining(fwk_id_t dev_id, + bool *has_alarm, + uint64_t *remaining_ticks) +{ + int status; + const struct dev_ctx *ctx; + const struct alarm_ctx *alarm_ctx; + const struct fwk_dlist_node *alarm_ctx_node; + + status = fwk_module_check_call(dev_id); if (status != FWK_SUCCESS) return status; - if (timestamp <= counter) - *remaining_ticks = 0; - else - *remaining_ticks = timestamp - counter; + if (has_alarm == NULL) + return FWK_E_PARAM; - return FWK_SUCCESS; + if (remaining_ticks == NULL) + return FWK_E_PARAM; + + ctx = &ctx_table[fwk_id_get_element_idx(dev_id)]; + + /* + * The timer interrupt is disabled to ensure that the alarm list is not + * modified while we are trying to read it below. + */ + ctx->driver->disable(ctx->driver_dev_id); + + *has_alarm = !fwk_list_is_empty(&ctx->alarms_active); + + if (*has_alarm) { + alarm_ctx_node = fwk_list_head(&ctx->alarms_active); + alarm_ctx = FWK_LIST_GET(alarm_ctx_node, struct alarm_ctx, node); + + status = _remaining(ctx, alarm_ctx->timestamp, remaining_ticks); + } + + ctx->driver->enable(ctx->driver_dev_id); + + return status; } static const struct mod_timer_api timer_api = { @@ -339,6 +394,7 @@ static const struct mod_timer_api timer_api = { .delay = delay, .wait = wait, .remaining = remaining, + .get_next_alarm_remaining = get_next_alarm_remaining, }; /* |