drivers: counter: Extend set channel alarm flags
Added flags for controling detection of setting alarm to late. Updated drivers to return -ENOTSUP when new option is requested. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
a37fce6171
commit
1baae96af6
2 changed files with 121 additions and 12 deletions
|
@ -23,3 +23,16 @@ COUNTER_HANDLER(stop)
|
||||||
COUNTER_HANDLER(start)
|
COUNTER_HANDLER(start)
|
||||||
COUNTER_HANDLER(get_top_value)
|
COUNTER_HANDLER(get_top_value)
|
||||||
COUNTER_HANDLER(get_max_relative_alarm)
|
COUNTER_HANDLER(get_max_relative_alarm)
|
||||||
|
|
||||||
|
Z_SYSCALL_HANDLER(counter_get_guard_period, dev, flags)
|
||||||
|
{
|
||||||
|
Z_OOPS(Z_SYSCALL_DRIVER_COUNTER(dev, get_guard_period));
|
||||||
|
return z_impl_counter_get_guard_period((struct device *)dev, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
Z_SYSCALL_HANDLER(counter_set_guard_period, dev, ticks, flags)
|
||||||
|
{
|
||||||
|
Z_OOPS(Z_SYSCALL_DRIVER_COUNTER(dev, set_guard_period));
|
||||||
|
return z_impl_counter_set_guard_period((struct device *)dev, ticks,
|
||||||
|
flags);
|
||||||
|
}
|
||||||
|
|
|
@ -61,7 +61,9 @@ extern "C" {
|
||||||
|
|
||||||
/**@} */
|
/**@} */
|
||||||
|
|
||||||
/**@defgroup COUNTER_ALARM_FLAGS Counter device capabilities
|
/**@defgroup COUNTER_ALARM_FLAGS Alarm configuration flags
|
||||||
|
*
|
||||||
|
* @brief Used in alarm configuration structure (@ref counter_alarm_cfg).
|
||||||
* @{ */
|
* @{ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,13 +74,35 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define COUNTER_ALARM_CFG_ABSOLUTE BIT(0)
|
#define COUNTER_ALARM_CFG_ABSOLUTE BIT(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Alarm flag enabling immediate expiration when driver detects that
|
||||||
|
* absolute alarm was set too late.
|
||||||
|
*
|
||||||
|
* Alarm callback must be called from the same context as if it was set on time.
|
||||||
|
*/
|
||||||
|
#define COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE BIT(1)
|
||||||
|
|
||||||
|
/**@} */
|
||||||
|
|
||||||
|
/**@defgroup COUNTER_GUARD_PERIOD_FLAGS Counter guard period flags
|
||||||
|
*
|
||||||
|
* @brief Used by @ref counter_set_guard_period and
|
||||||
|
* @ref counter_get_guard_period.
|
||||||
|
* @{ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Identifies guard period needed for detection of late setting of
|
||||||
|
* absolute alarm (see @ref counter_set_channel_alarm).
|
||||||
|
*/
|
||||||
|
#define COUNTER_GUARD_PERIOD_LATE_TO_SET BIT(0)
|
||||||
|
|
||||||
/**@} */
|
/**@} */
|
||||||
|
|
||||||
/** @brief Alarm callback
|
/** @brief Alarm callback
|
||||||
*
|
*
|
||||||
* @param dev Pointer to the device structure for the driver instance.
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
* @param chan_id Channel ID.
|
* @param chan_id Channel ID.
|
||||||
* @param ticks Counter value that triggered the callback.
|
* @param ticks Counter value that triggered the alarm.
|
||||||
* @param user_data User data.
|
* @param user_data User data.
|
||||||
*/
|
*/
|
||||||
typedef void (*counter_alarm_callback_t)(struct device *dev,
|
typedef void (*counter_alarm_callback_t)(struct device *dev,
|
||||||
|
@ -88,16 +112,16 @@ typedef void (*counter_alarm_callback_t)(struct device *dev,
|
||||||
/** @brief Alarm callback structure.
|
/** @brief Alarm callback structure.
|
||||||
*
|
*
|
||||||
* @param callback Callback called on alarm (cannot be NULL).
|
* @param callback Callback called on alarm (cannot be NULL).
|
||||||
* @param ticks Ticks that triggers the alarm. In case of absolute flag is set,
|
* @param ticks Number of ticks that triggers the alarm. It can be relative (to
|
||||||
* maximal value that can be set equals top value
|
* now) or absolute value (see @ref COUNTER_ALARM_CFG_ABSOLUTE).
|
||||||
* (@ref counter_get_top_value). Otherwise
|
* Absolute alarm cannot be set further in future than top_value
|
||||||
* @ref counter_get_max_relative_alarm() returns maximal value that
|
* decremented by the guard period. Relative alarm ticks cannot
|
||||||
* can be set. If counter is clock driven then ticks can be
|
* exceed current top value (see @ref counter_get_top_value).
|
||||||
* converted to microseconds (see @ref counter_ticks_to_us).
|
* If counter is clock driven then ticks can be converted to
|
||||||
* Alternatively, counter implementation may count asynchronous
|
* microseconds (see @ref counter_ticks_to_us). Alternatively,
|
||||||
* events.
|
* counter implementation may count asynchronous events.
|
||||||
* @param user_data User data returned in callback.
|
* @param user_data User data returned in callback.
|
||||||
* @param flags Alarm flags.
|
* @param flags Alarm flags. See @ref COUNTER_ALARM_FLAGS.
|
||||||
*/
|
*/
|
||||||
struct counter_alarm_cfg {
|
struct counter_alarm_cfg {
|
||||||
counter_alarm_callback_t callback;
|
counter_alarm_callback_t callback;
|
||||||
|
@ -156,6 +180,9 @@ typedef int (*counter_api_set_top_value)(struct device *dev,
|
||||||
typedef u32_t (*counter_api_get_pending_int)(struct device *dev);
|
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_top_value)(struct device *dev);
|
||||||
typedef u32_t (*counter_api_get_max_relative_alarm)(struct device *dev);
|
typedef u32_t (*counter_api_get_max_relative_alarm)(struct device *dev);
|
||||||
|
typedef u32_t (*counter_api_get_guard_period)(struct device *dev, u32_t flags);
|
||||||
|
typedef int (*counter_api_set_guard_period)(struct device *dev, u32_t ticks,
|
||||||
|
u32_t flags);
|
||||||
typedef void *(*counter_api_get_user_data)(struct device *dev);
|
typedef void *(*counter_api_get_user_data)(struct device *dev);
|
||||||
|
|
||||||
struct counter_driver_api {
|
struct counter_driver_api {
|
||||||
|
@ -168,6 +195,8 @@ struct counter_driver_api {
|
||||||
counter_api_get_pending_int get_pending_int;
|
counter_api_get_pending_int get_pending_int;
|
||||||
counter_api_get_top_value get_top_value;
|
counter_api_get_top_value get_top_value;
|
||||||
counter_api_get_max_relative_alarm get_max_relative_alarm;
|
counter_api_get_max_relative_alarm get_max_relative_alarm;
|
||||||
|
counter_api_get_guard_period get_guard_period;
|
||||||
|
counter_api_set_guard_period set_guard_period;
|
||||||
counter_api_get_user_data get_user_data;
|
counter_api_get_user_data get_user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -337,6 +366,7 @@ static inline u32_t z_impl_counter_read(struct device *dev)
|
||||||
* @retval -ENOTSUP if request is not supported (device does not support
|
* @retval -ENOTSUP if request is not supported (device does not support
|
||||||
* interrupts or requested channel).
|
* interrupts or requested channel).
|
||||||
* @retval -EINVAL if alarm settings are invalid.
|
* @retval -EINVAL if alarm settings are invalid.
|
||||||
|
* @retval -ETIME if absolute alarm was set too late.
|
||||||
*/
|
*/
|
||||||
static inline int counter_set_channel_alarm(struct device *dev, u8_t chan_id,
|
static inline int counter_set_channel_alarm(struct device *dev, u8_t chan_id,
|
||||||
const struct counter_alarm_cfg *alarm_cfg)
|
const struct counter_alarm_cfg *alarm_cfg)
|
||||||
|
@ -461,7 +491,7 @@ static inline u32_t z_impl_counter_get_top_value(struct device *dev)
|
||||||
*
|
*
|
||||||
* @return Max alarm value.
|
* @return Max alarm value.
|
||||||
*/
|
*/
|
||||||
__syscall u32_t counter_get_max_relative_alarm(struct device *dev);
|
__deprecated __syscall u32_t counter_get_max_relative_alarm(struct device *dev);
|
||||||
|
|
||||||
static inline u32_t z_impl_counter_get_max_relative_alarm(struct device *dev)
|
static inline u32_t z_impl_counter_get_max_relative_alarm(struct device *dev)
|
||||||
{
|
{
|
||||||
|
@ -471,6 +501,72 @@ static inline u32_t z_impl_counter_get_max_relative_alarm(struct device *dev)
|
||||||
return api->get_max_relative_alarm(dev);
|
return api->get_max_relative_alarm(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set guard period in counter ticks.
|
||||||
|
*
|
||||||
|
* Setting non-zero guard period enables detection of setting absolute alarm
|
||||||
|
* too late. It limits how far in the future absolute alarm can be set.
|
||||||
|
*
|
||||||
|
* Detection of too late setting is vital since if it is not detected alarm
|
||||||
|
* is delayed by full period of the counter (up to 32 bits). Because of the
|
||||||
|
* wrapping, it is impossible to distinguish alarm which is short in the past
|
||||||
|
* from alarm which is targeted to expire after full counter period. In order to
|
||||||
|
* detect too late setting, longest possible alarm is limited. Absolute value
|
||||||
|
* cannot exceed: (now + top_value - guard_period) % top_value.
|
||||||
|
*
|
||||||
|
* Guard period depends on application and counter frequency. If it is expected
|
||||||
|
* that absolute alarms setting might be delayed then guard period should
|
||||||
|
* exceed maximal potential delay. If use case allows, guard period can be set
|
||||||
|
* very high (e.g. half of the counter top value).
|
||||||
|
*
|
||||||
|
* After initialization guard period is set to 0 and late detection is disabled.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param ticks Guard period in counter ticks.
|
||||||
|
* @param flags See @ref COUNTER_GUARD_PERIOD_FLAGS.
|
||||||
|
*
|
||||||
|
* @retval 0 if successful.
|
||||||
|
* @retval -ENOTSUP if function or flags are not supported.
|
||||||
|
* @retval -EINVAL if ticks value is invalid.
|
||||||
|
*/
|
||||||
|
__syscall int counter_set_guard_period(struct device *dev, u32_t ticks,
|
||||||
|
u32_t flags);
|
||||||
|
|
||||||
|
static inline int z_impl_counter_set_guard_period(struct device *dev,
|
||||||
|
u32_t ticks, u32_t flags)
|
||||||
|
{
|
||||||
|
const struct counter_driver_api *api =
|
||||||
|
(struct counter_driver_api *)dev->driver_api;
|
||||||
|
|
||||||
|
if (!api->set_guard_period) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return api->set_guard_period(dev, ticks, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return guard period.
|
||||||
|
*
|
||||||
|
* See @ref counter_set_guard_period.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param flags See @ref COUNTER_GUARD_PERIOD_FLAGS.
|
||||||
|
*
|
||||||
|
* @return Guard period given in counter ticks or 0 if function or flags are
|
||||||
|
* not supported.
|
||||||
|
*/
|
||||||
|
__syscall u32_t counter_get_guard_period(struct device *dev, u32_t flags);
|
||||||
|
|
||||||
|
static inline u32_t z_impl_counter_get_guard_period(struct device *dev,
|
||||||
|
u32_t flags)
|
||||||
|
{
|
||||||
|
const struct counter_driver_api *api =
|
||||||
|
(struct counter_driver_api *)dev->driver_api;
|
||||||
|
|
||||||
|
return (api->get_guard_period) ? api->get_guard_period(dev, flags) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Deprecated counter callback. */
|
/* Deprecated counter callback. */
|
||||||
typedef void (*counter_callback_t)(struct device *dev, void *user_data);
|
typedef void (*counter_callback_t)(struct device *dev, void *user_data);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue