counter: Update counter API in order to provide more flexibility

This commit introduces new top_value setting configuration structure
with flag for controlling resetting of the counter during change of
top value.

Such change allows for #12068 implementation on hardware which
does not provide alarms.

Signed-off-by: Piotr Zięcik <piotr.ziecik@nordicsemi.no>
Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
Signed-off-by: Benjamin Valentin <benjamin.valentin@ml-pa.com>
This commit is contained in:
Piotr Zięcik 2019-03-21 16:31:16 +01:00 committed by Carles Cufí
commit 69406e0f9c
14 changed files with 248 additions and 125 deletions

View file

@ -39,6 +39,28 @@ extern "C" {
/**@} */
/**@defgroup COUNTER_TOP_FLAGS Flags used by @ref counter_top_cfg.
* @{
*/
/**
* @brief Flag preventing counter reset when top value is changed.
*
* If flags is set then counter is free running while top value is updated,
* otherwise counter is reset (see @ref counter_set_top_value()).
*/
#define COUNTER_TOP_CFG_DONT_RESET BIT(0)
/**
* @brief Flag instructing counter to reset itself if changing top value
* results in counter going out of new top value bound.
*
* See @ref COUNTER_TOP_CFG_DONT_RESET.
*/
#define COUNTER_TOP_CFG_RESET_WHEN_LATE BIT(1)
/**@} */
/** @brief Alarm callback
*
* @param dev Pointer to the device structure for the driver instance.
@ -80,6 +102,21 @@ struct counter_alarm_cfg {
*/
typedef void (*counter_top_callback_t)(struct device *dev, void *user_data);
/** @brief Top value configuration structure.
*
* @param ticks Top value.
* @param callback Callback function. Can be NULL.
* @param user_data User data passed to callback function. Not valid if
* callback is NULL.
* @param flags Flags. See @ref COUNTER_TOP_FLAGS.
*/
struct counter_top_cfg {
u32_t ticks;
counter_top_callback_t callback;
void *user_data;
u32_t flags;
};
/** @brief Structure with generic counter features.
*
* @param max_top_value Maximal (default) top value on which counter is reset
@ -103,9 +140,8 @@ typedef u32_t (*counter_api_read)(struct device *dev);
typedef int (*counter_api_set_alarm)(struct device *dev, u8_t chan_id,
const struct counter_alarm_cfg *alarm_cfg);
typedef int (*counter_api_cancel_alarm)(struct device *dev, u8_t chan_id);
typedef int (*counter_api_set_top_value)(struct device *dev, u32_t ticks,
counter_top_callback_t callback,
void *user_data);
typedef int (*counter_api_set_top_value)(struct device *dev,
const struct counter_top_cfg *cfg);
typedef u32_t (*counter_api_get_pending_int)(struct device *dev);
typedef u32_t (*counter_api_get_top_value)(struct device *dev);
typedef u32_t (*counter_api_get_max_relative_alarm)(struct device *dev);
@ -332,34 +368,38 @@ static inline int counter_cancel_channel_alarm(struct device *dev,
/**
* @brief Set counter top value.
*
* Function sets top value and resets the counter to 0 or top value
* depending on counter direction. On turnaround, counter is reset and optional
* callback is periodically called. Top value can only be changed when there
* is no active channel alarm.
* Function sets top value and optionally resets the counter to 0 or top value
* depending on counter direction. On turnaround, counter can be reset and
* optional callback is periodically called. Top value can only be changed when
* there is no active channel alarm.
*
* @ref COUNTER_TOP_CFG_DONT_RESET prevents counter reset. When counter is
* running while top value is updated, it is possible that counter progresses
* outside the new top value. In that case, error is returned and optionally
* driver can reset the counter (see @ref COUNTER_TOP_CFG_RESET_WHEN_LATE).
*
* @param dev Pointer to the device structure for the driver instance.
* @param ticks Top value.
* @param callback Callback function. Can be NULL.
* @param user_data User data passed to callback function. Not valid if
* callback is NULL.
* @param cfg Configuration. Cannot be NULL.
*
* @retval 0 If successful.
* @retval -ENOTSUP if request is not supported (e.g. top value cannot be
* changed).
* changed or counter cannot/must be reset during top value
update).
* @retval -EBUSY if any alarm is active.
* @retval -ETIME if @ref COUNTER_TOP_CFG_DONT_RESET was set and new top value
* is smaller than current counter value (counter counting up).
*/
static inline int counter_set_top_value(struct device *dev, u32_t ticks,
counter_top_callback_t callback,
void *user_data)
static inline int counter_set_top_value(struct device *dev,
const struct counter_top_cfg *cfg)
{
const struct counter_driver_api *api =
(struct counter_driver_api *)dev->driver_api;
if (ticks > counter_get_max_top_value(dev)) {
if (cfg->ticks > counter_get_max_top_value(dev)) {
return -EINVAL;
}
return api->set_top_value(dev, ticks, callback, user_data);
return api->set_top_value(dev, cfg);
}
/**
@ -430,7 +470,14 @@ __deprecated static inline int counter_set_alarm(struct device *dev,
counter_callback_t callback,
u32_t count, void *user_data)
{
return counter_set_top_value(dev, count, callback, user_data);
struct counter_top_cfg cfg = {
.ticks = count,
.callback = callback,
.user_data = user_data,
.flags = 0
};
return counter_set_top_value(dev, &cfg);
}
/**