drivers: counter: add counter_get_value(), deprecate counter_read()

Introduce a new counter API function for reading the current counter
value (counter_get_value()) and deprecate the former counter_read() in
favor of this.

Update all drivers and calling code to match the new counter API.

The previous counter driver API function for reading the current value
of the counter (counter_read()) did not support indicating whether the
read suceeded. This is fine for counters internal to the SoC where the
read always succeeds but insufficient for external counters (e.g. I2C
or SPI slaves).

Fixes #21846.

Signed-off-by: Henrik Brix Andersen <henrik@brixandersen.dk>
This commit is contained in:
Henrik Brix Andersen 2020-01-18 15:24:32 +01:00 committed by Anas Nashif
commit c894a6db4d
19 changed files with 162 additions and 58 deletions

View file

@ -124,11 +124,11 @@ static u32_t hinnant(int y, int m, int d)
}
/*
* Returns the Unix epoch time (assuming UTC) read from the CMOS RTC.
* Get the Unix epoch time (assuming UTC) read from the CMOS RTC.
* This function is long, but linear and easy to follow.
*/
u32_t read(struct device *dev)
int get_value(struct device *dev, u32_t *ticks)
{
struct state state, state2;
u64_t *pun = (u64_t *) &state;
@ -188,7 +188,8 @@ u32_t read(struct device *dev)
epoch += state.minute * 60; /* seconds per minute */
epoch += state.second;
return epoch;
*ticks = epoch;
return 0;
}
static int init(struct device *dev)
@ -204,7 +205,7 @@ static const struct counter_config_info info = {
};
static const struct counter_driver_api api = {
.read = read
.get_value = get_value
};
DEVICE_AND_API_INIT(counter_cmos, "CMOS", init, NULL, &info,

View file

@ -83,11 +83,12 @@ static int counter_gecko_stop(struct device *dev)
return 0;
}
static u32_t counter_gecko_read(struct device *dev)
static int counter_gecko_get_value(struct device *dev, u32_t *ticks)
{
ARG_UNUSED(dev);
return RTCC_CounterGet();
*ticks = RTCC_CounterGet();
return 0;
}
static int counter_gecko_set_top_value(struct device *dev,
@ -160,7 +161,7 @@ static u32_t counter_gecko_get_max_relative_alarm(struct device *dev)
static int counter_gecko_set_alarm(struct device *dev, u8_t chan_id,
const struct counter_alarm_cfg *alarm_cfg)
{
u32_t count = counter_gecko_read(dev);
u32_t count = RTCC_CounterGet();
struct counter_gecko_data *const dev_data = DEV_DATA(dev);
u32_t top_value = counter_gecko_get_top_value(dev);
u32_t ccv;
@ -309,7 +310,7 @@ static int counter_gecko_init(struct device *dev)
static const struct counter_driver_api counter_gecko_driver_api = {
.start = counter_gecko_start,
.stop = counter_gecko_stop,
.read = counter_gecko_read,
.get_value = counter_gecko_get_value,
.set_alarm = counter_gecko_set_alarm,
.cancel_alarm = counter_gecko_cancel_alarm,
.set_top_value = counter_gecko_set_top_value,

View file

@ -64,12 +64,14 @@ static inline u64_t z_vrfy_counter_ticks_to_us(const struct device *dev,
}
#include <syscalls/counter_ticks_to_us_mrsh.c>
static inline u32_t z_vrfy_counter_read(struct device *dev)
static inline int z_vrfy_counter_get_value(struct device *dev,
u32_t *ticks)
{
Z_OOPS(Z_SYSCALL_DRIVER_COUNTER(dev, read));
return z_impl_counter_read((struct device *)dev);
Z_OOPS(Z_SYSCALL_DRIVER_COUNTER(dev, get_value));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(ticks, sizeof(ticks)));
return z_impl_counter_get_value((struct device *)dev, ticks);
}
#include <syscalls/counter_read_mrsh.c>
#include <syscalls/counter_get_value_mrsh.c>
static inline int z_vrfy_counter_set_channel_alarm(struct device *dev,
u8_t chan_id, const struct counter_alarm_cfg *alarm_cfg)

View file

@ -86,14 +86,13 @@ static int imx_epit_stop(struct device *dev)
return 0;
}
static u32_t imx_epit_read(struct device *dev)
static int imx_epit_get_value(struct device *dev, u32_t *ticks)
{
EPIT_Type *base = get_epit_config(dev)->base;
u32_t value;
value = EPIT_GetCounterLoadValue(base) - EPIT_ReadCounter(base);
*ticks = EPIT_GetCounterLoadValue(base) - EPIT_ReadCounter(base);
return value;
return 0;
}
static int imx_epit_set_top_value(struct device *dev,
@ -143,7 +142,7 @@ static u32_t imx_epit_get_max_relative_alarm(struct device *dev)
static const struct counter_driver_api imx_epit_driver_api = {
.start = imx_epit_start,
.stop = imx_epit_stop,
.read = imx_epit_read,
.get_value = imx_epit_get_value,
.set_top_value = imx_epit_set_top_value,
.get_pending_int = imx_epit_get_pending_int,
.get_top_value = imx_epit_get_top_value,

View file

@ -112,6 +112,12 @@ static u32_t rtc_stm32_read(struct device *dev)
return ticks;
}
static int rtc_stm32_get_value(struct device *dev, u32_t *ticks)
{
*ticks = rtc_stm32_read(dev);
return 0;
}
static int rtc_stm32_set_alarm(struct device *dev, u8_t chan_id,
const struct counter_alarm_cfg *alarm_cfg)
{
@ -353,7 +359,7 @@ static const struct rtc_stm32_config rtc_config = {
static const struct counter_driver_api rtc_stm32_driver_api = {
.start = rtc_stm32_start,
.stop = rtc_stm32_stop,
.read = rtc_stm32_read,
.get_value = rtc_stm32_get_value,
.set_alarm = rtc_stm32_set_alarm,
.cancel_alarm = rtc_stm32_cancel_alarm,
.set_top_value = rtc_stm32_set_top_value,

View file

@ -96,11 +96,12 @@ static int counter_xec_stop(struct device *dev)
return 0;
}
static u32_t counter_xec_read(struct device *dev)
static int counter_xec_get_value(struct device *dev, u32_t *ticks)
{
BTMR_Type *counter = COUNTER_XEC_REG_BASE(dev);
return counter->CNT;
*ticks = counter->CNT;
return 0;
}
static int counter_xec_set_alarm(struct device *dev, u8_t chan_id,
@ -275,7 +276,7 @@ static void counter_xec_isr(struct device *dev)
static const struct counter_driver_api counter_xec_api = {
.start = counter_xec_start,
.stop = counter_xec_stop,
.read = counter_xec_read,
.get_value = counter_xec_get_value,
.set_alarm = counter_xec_set_alarm,
.cancel_alarm = counter_xec_cancel_alarm,
.set_top_value = counter_xec_set_top_value,

View file

@ -42,11 +42,12 @@ static int mcux_gpt_stop(struct device *dev)
return 0;
}
static u32_t mcux_gpt_read(struct device *dev)
static int mcux_gpt_get_value(struct device *dev, u32_t *ticks)
{
const struct mcux_gpt_config *config = dev->config->config_info;
return GPT_GetCurrentTimerCount(config->base);
*ticks = GPT_GetCurrentTimerCount(config->base);
return 0;
}
static int mcux_gpt_set_alarm(struct device *dev, u8_t chan_id,
@ -55,7 +56,7 @@ static int mcux_gpt_set_alarm(struct device *dev, u8_t chan_id,
const struct mcux_gpt_config *config = dev->config->config_info;
struct mcux_gpt_data *data = dev->driver_data;
u32_t current = mcux_gpt_read(dev);
u32_t current = GPT_GetCurrentTimerCount(config->base);
u32_t ticks = alarm_cfg->ticks;
if (chan_id != 0) {
@ -102,7 +103,7 @@ void mcux_gpt_isr(void *p)
struct device *dev = p;
const struct mcux_gpt_config *config = dev->config->config_info;
struct mcux_gpt_data *data = dev->driver_data;
u32_t current = mcux_gpt_read(dev);
u32_t current = GPT_GetCurrentTimerCount(config->base);
u32_t status;
status = GPT_GetStatusFlags(config->base, kGPT_OutputCompare1Flag |
@ -189,7 +190,7 @@ static int mcux_gpt_init(struct device *dev)
static const struct counter_driver_api mcux_gpt_driver_api = {
.start = mcux_gpt_start,
.stop = mcux_gpt_stop,
.read = mcux_gpt_read,
.get_value = mcux_gpt_get_value,
.set_alarm = mcux_gpt_set_alarm,
.cancel_alarm = mcux_gpt_cancel_alarm,
.set_top_value = mcux_gpt_set_top_value,

View file

@ -79,6 +79,12 @@ static u32_t mcux_rtc_read(struct device *dev)
return ticks;
}
static int mcux_rtc_get_value(struct device *dev, u32_t *ticks)
{
*ticks = mcux_rtc_read(dev);
return 0;
}
static int mcux_rtc_set_alarm(struct device *dev, u8_t chan_id,
const struct counter_alarm_cfg *alarm_cfg)
{
@ -245,7 +251,7 @@ static int mcux_rtc_init(struct device *dev)
static const struct counter_driver_api mcux_rtc_driver_api = {
.start = mcux_rtc_start,
.stop = mcux_rtc_stop,
.read = mcux_rtc_read,
.get_value = mcux_rtc_get_value,
.set_alarm = mcux_rtc_set_alarm,
.cancel_alarm = mcux_rtc_cancel_alarm,
.set_top_value = mcux_rtc_set_top_value,

View file

@ -97,6 +97,12 @@ static u32_t read(struct device *dev)
return nrf_rtc_counter_get(get_nrfx_config(dev)->rtc);
}
static int get_value(struct device *dev, u32_t *ticks)
{
*ticks = read(dev);
return 0;
}
/* Return true if value equals 2^n - 1 */
static inline bool is_bit_mask(u32_t val)
{
@ -637,7 +643,7 @@ static void irq_handler(struct device *dev)
static const struct counter_driver_api counter_nrfx_driver_api = {
.start = start,
.stop = stop,
.read = read,
.get_value = get_value,
.set_alarm = set_channel_alarm,
.cancel_alarm = cancel_alarm,
.set_top_value = set_top_value,

View file

@ -98,6 +98,12 @@ static u32_t read(struct device *dev)
return nrf_timer_cc_get(timer, COUNTER_READ_CC);
}
static int get_value(struct device *dev, u32_t *ticks)
{
*ticks = read(dev);
return 0;
}
/* Return true if value equals 2^n - 1 */
static inline bool is_bit_mask(u32_t val)
{
@ -365,7 +371,7 @@ static void irq_handler(struct device *dev)
static const struct counter_driver_api counter_nrfx_driver_api = {
.start = start,
.stop = stop,
.read = read,
.get_value = get_value,
.set_alarm = set_alarm,
.cancel_alarm = cancel_alarm,
.set_top_value = set_top_value,

View file

@ -113,6 +113,12 @@ static u32_t counter_sam0_tc32_read(struct device *dev)
return tc->COUNT.reg;
}
static int counter_sam0_tc32_get_value(struct device *dev, u32_t *ticks)
{
*ticks = counter_sam0_tc32_read(dev);
return 0;
}
static void counter_sam0_tc32_relative_alarm(struct device *dev, u32_t ticks)
{
struct counter_sam0_tc32_data *data = DEV_DATA(dev);
@ -385,7 +391,7 @@ static int counter_sam0_tc32_initialize(struct device *dev)
static const struct counter_driver_api counter_sam0_tc32_driver_api = {
.start = counter_sam0_tc32_start,
.stop = counter_sam0_tc32_stop,
.read = counter_sam0_tc32_read,
.get_value = counter_sam0_tc32_get_value,
.set_alarm = counter_sam0_tc32_set_alarm,
.cancel_alarm = counter_sam0_tc32_cancel_alarm,
.set_top_value = counter_sam0_tc32_set_top_value,

View file

@ -59,13 +59,14 @@ static int dtmr_cmsdk_apb_stop(struct device *dev)
return 0;
}
static u32_t dtmr_cmsdk_apb_read(struct device *dev)
static int dtmr_cmsdk_apb_get_value(struct device *dev, u32_t *ticks)
{
const struct dtmr_cmsdk_apb_cfg * const cfg =
dev->config->config_info;
struct dtmr_cmsdk_apb_dev_data *data = dev->driver_data;
return data->load - cfg->dtimer->timer1value;
*ticks = data->load - cfg->dtimer->timer1value;
return 0;
}
static int dtmr_cmsdk_apb_set_top_value(struct device *dev,
@ -123,7 +124,7 @@ static u32_t dtmr_cmsdk_apb_get_pending_int(struct device *dev)
static const struct counter_driver_api dtmr_cmsdk_apb_api = {
.start = dtmr_cmsdk_apb_start,
.stop = dtmr_cmsdk_apb_stop,
.read = dtmr_cmsdk_apb_read,
.get_value = dtmr_cmsdk_apb_get_value,
.set_top_value = dtmr_cmsdk_apb_set_top_value,
.get_pending_int = dtmr_cmsdk_apb_get_pending_int,
.get_top_value = dtmr_cmsdk_apb_get_top_value,

View file

@ -58,14 +58,15 @@ static int tmr_cmsdk_apb_stop(struct device *dev)
return 0;
}
static u32_t tmr_cmsdk_apb_read(struct device *dev)
static int tmr_cmsdk_apb_get_value(struct device *dev, u32_t *ticks)
{
const struct tmr_cmsdk_apb_cfg * const cfg =
dev->config->config_info;
struct tmr_cmsdk_apb_dev_data *data = dev->driver_data;
/* Return Counter Value */
return data->load - cfg->timer->value;
/* Get Counter Value */
*ticks = data->load - cfg->timer->value;
return 0;
}
static int tmr_cmsdk_apb_set_top_value(struct device *dev,
@ -118,7 +119,7 @@ static u32_t tmr_cmsdk_apb_get_pending_int(struct device *dev)
static const struct counter_driver_api tmr_cmsdk_apb_api = {
.start = tmr_cmsdk_apb_start,
.stop = tmr_cmsdk_apb_stop,
.read = tmr_cmsdk_apb_read,
.get_value = tmr_cmsdk_apb_get_value,
.set_top_value = tmr_cmsdk_apb_set_top_value,
.get_pending_int = tmr_cmsdk_apb_get_pending_int,
.get_top_value = tmr_cmsdk_apb_get_top_value,

View file

@ -106,7 +106,16 @@ void BoardCriticalSectionEnd(uint32_t *mask)
uint32_t RtcGetTimerElapsedTime(void)
{
return counter_read(dev_data.counter);
u32_t ticks;
int err;
err = counter_get_value(dev_data.counter, &ticks);
if (err) {
LOG_ERR("Failed to read counter value (err %d)", err);
return 0;
}
return ticks;
}
u32_t RtcGetMinimumTimeout(void)

View file

@ -171,7 +171,7 @@ struct counter_config_info {
typedef int (*counter_api_start)(struct device *dev);
typedef int (*counter_api_stop)(struct device *dev);
typedef u32_t (*counter_api_read)(struct device *dev);
typedef int (*counter_api_get_value)(struct device *dev, u32_t *ticks);
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);
@ -187,7 +187,7 @@ typedef int (*counter_api_set_guard_period)(struct device *dev, u32_t ticks,
struct counter_driver_api {
counter_api_start start;
counter_api_stop stop;
counter_api_read read;
counter_api_get_value get_value;
counter_api_set_alarm set_alarm;
counter_api_cancel_alarm cancel_alarm;
counter_api_set_top_value set_top_value;
@ -345,19 +345,21 @@ static inline int z_impl_counter_stop(struct device *dev)
}
/**
* @brief Read current counter value.
* @brief Get current counter value.
* @param dev Pointer to the device structure for the driver instance.
* @param ticks Pointer to where to store the current counter value
*
* @return 32-bit value
* @retval 0 If successful.
* @retval Negative error code on failure getting the counter value
*/
__syscall u32_t counter_read(struct device *dev);
__syscall int counter_get_value(struct device *dev, u32_t *ticks);
static inline u32_t z_impl_counter_read(struct device *dev)
static inline int z_impl_counter_get_value(struct device *dev, u32_t *ticks)
{
const struct counter_driver_api *api =
(struct counter_driver_api *)dev->driver_api;
return api->read(dev);
return api->get_value(dev, ticks);
}
/**
@ -590,6 +592,18 @@ static inline u32_t z_impl_counter_get_guard_period(struct device *dev,
/* Deprecated counter callback. */
typedef void (*counter_callback_t)(struct device *dev, void *user_data);
/* Deprecated counter read function. Use counter_get_value() instead. */
__deprecated static inline u32_t counter_read(struct device *dev)
{
u32_t ticks;
if (counter_get_value(dev, &ticks) == 0) {
return ticks;
}
return 0;
}
#ifdef __cplusplus
}
#endif

View file

@ -19,12 +19,21 @@ static void test_counter_interrupt_fn(struct device *counter_dev,
u8_t chan_id, u32_t ticks,
void *user_data)
{
u32_t now_ticks = counter_read(counter_dev);
u64_t now_usec = counter_ticks_to_us(counter_dev, now_ticks);
int now_sec = (int)(now_usec / USEC_PER_SEC);
struct counter_alarm_cfg *config = user_data;
u32_t now_ticks;
u64_t now_usec;
int now_sec;
int err;
err = counter_get_value(counter_dev, &now_ticks);
if (err) {
printk("Failed to read counter value (err %d)", err);
return;
}
now_usec = counter_ticks_to_us(counter_dev, now_ticks);
now_sec = (int)(now_usec / USEC_PER_SEC);
printk("!!! Alarm !!!\n");
printk("Now: %u\n", now_sec);

View file

@ -12,11 +12,21 @@
static u32_t sync(struct device *cmos)
{
u32_t this, last;
int err;
err = counter_get_value(cmos, &this);
if (err) {
printk("\tCan't read CMOS clock device.\n");
return 0;
}
this = counter_read(cmos);
do {
last = this;
this = counter_read(cmos);
err = counter_get_value(cmos, &this);
if (err) {
printk("\tCan't read CMOS clock device.\n");
return 0;
}
} while (last == this);
return z_timer_cycle_get_32();

View file

@ -171,7 +171,9 @@ void test_set_top_value_with_alarm_instance(const char *dev_name)
k_busy_wait(5000);
cnt = counter_read(dev);
err = counter_get_value(dev, &cnt);
zassert_true(err == 0, "%s: Counter read failed (err: %d)", dev_name,
err);
if (counter_is_counting_up(dev)) {
err = (cnt > 0) ? 0 : 1;
} else {
@ -217,7 +219,9 @@ void test_set_top_value_without_alarm_instance(const char *dev_name)
k_busy_wait(5000);
cnt = counter_read(dev);
err = counter_get_value(dev, &cnt);
zassert_true(err == 0, "%s: Counter read failed (err: %d)", dev_name,
err);
if (counter_is_counting_up(dev)) {
err = (cnt > 0) ? 0 : 1;
} else {
@ -244,7 +248,12 @@ void test_set_top_value_without_alarm(void)
static void alarm_handler(struct device *dev, u8_t chan_id, u32_t counter,
void *user_data)
{
u32_t now = counter_read(dev);
u32_t now;
int err;
err = counter_get_value(dev, &now);
zassert_true(err == 0, "%s: Counter read failed (err: %d)",
dev->config->name, err);
if (counter_is_counting_up(dev)) {
zassert_true(now >= counter,
@ -569,7 +578,10 @@ void test_late_alarm_instance(const char *dev_name)
"%s: Expected %d callbacks, got %d\n",
dev_name, 1, alarm_cnt);
alarm_cfg.ticks = counter_read(dev);
err = counter_get_value(dev, &(alarm_cfg.ticks));
zassert_true(err == 0, "%s: Counter read failed (err: %d)", dev_name,
err);
err = counter_set_channel_alarm(dev, 0, &alarm_cfg);
zassert_equal(-ETIME, err, "%s: Failed to set an alarm (err: %d)",
dev_name, err);
@ -610,7 +622,10 @@ void test_late_alarm_error_instance(const char *dev_name)
"%s: Failed to detect late setting (err: %d)",
dev_name, err);
alarm_cfg.ticks = counter_read(dev);
err = counter_get_value(dev, &(alarm_cfg.ticks));
zassert_true(err == 0, "%s: Counter read failed (err: %d)", dev_name,
err);
err = counter_set_channel_alarm(dev, 0, &alarm_cfg);
zassert_equal(-ETIME, err,
"%s: Counter failed to detect late setting (err: %d)",
@ -755,7 +770,11 @@ static void test_cancelled_alarm_does_not_expire_instance(const char *dev_name)
for (int i = 0; i < us/2; ++i) {
alarm_cfg.ticks = counter_read(dev) + ticks;
err = counter_get_value(dev, &(alarm_cfg.ticks));
zassert_true(err == 0, "%s: Counter read failed (err: %d)",
dev_name, err);
alarm_cfg.ticks += ticks;
err = counter_set_channel_alarm(dev, 0, &alarm_cfg);
zassert_equal(0, err, "%s: Failed to set an alarm (err: %d)",
dev_name, err);

View file

@ -19,13 +19,19 @@ void test_cmos_rate(void)
{
struct device *cmos;
u32_t start, elapsed;
int err;
cmos = device_get_binding("CMOS");
zassert_true(cmos != NULL, "can't find CMOS counter device");
start = counter_read(cmos);
err = counter_get_value(cmos, &start);
zassert_true(err == 0, "failed to read CMOS counter device");
k_sleep(DELAY_MS);
elapsed = counter_read(cmos) - start;
err = counter_get_value(cmos, &elapsed);
zassert_true(err == 0, "failed to read CMOS counter device");
elapsed -= start;
zassert_true(elapsed >= MIN_BOUND, "busted minimum bound");
zassert_true(elapsed <= MAX_BOUND, "busted maximum bound");