From 649bb3bb4438b7cddc5ee45f63d78d4c5f9b6b33 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Thu, 19 May 2022 17:08:14 -0500 Subject: [PATCH] drivers: counter: Update CTimer to fix alarm setting 1. Make sure the relative alarm value is set correctly 2. Add a Kconfig to give user the option of reserving a CTimer channel for implementing the set_top_value function Signed-off-by: Mahesh Mahadevan --- drivers/counter/Kconfig.mcux_ctimer | 8 ++++++++ drivers/counter/counter_mcux_ctimer.c | 29 +++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/counter/Kconfig.mcux_ctimer b/drivers/counter/Kconfig.mcux_ctimer index fc97d9b17d2..154d19de567 100644 --- a/drivers/counter/Kconfig.mcux_ctimer +++ b/drivers/counter/Kconfig.mcux_ctimer @@ -8,3 +8,11 @@ config COUNTER_MCUX_CTIMER depends on HAS_MCUX_CTIMER help Enable support for MCUX CTIMER driver. + +config COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP + bool "reserve a ctimer channel to set the top value" + default y + depends on COUNTER_MCUX_CTIMER + help + This reserves a CTimer channel to set the top value. Without + this the set top value can be set only to the max counter value. diff --git a/drivers/counter/counter_mcux_ctimer.c b/drivers/counter/counter_mcux_ctimer.c index f4bfb8d9236..dc86e5ed43c 100644 --- a/drivers/counter/counter_mcux_ctimer.c +++ b/drivers/counter/counter_mcux_ctimer.c @@ -12,8 +12,12 @@ #include LOG_MODULE_REGISTER(mcux_ctimer, CONFIG_COUNTER_LOG_LEVEL); +#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP /* One of the CTimer channels is reserved to implement set_top_value API */ #define NUM_CHANNELS 3 +#else +#define NUM_CHANNELS 4 +#endif struct mcux_lpc_ctimer_channel_data { counter_alarm_callback_t alarm_callback; @@ -70,6 +74,8 @@ static int mcux_lpc_ctimer_get_value(const struct device *dev, uint32_t *ticks) static uint32_t mcux_lpc_ctimer_get_top_value(const struct device *dev) { const struct mcux_lpc_ctimer_config *config = dev->config; + +#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP CTIMER_Type *base = config->base; /* Return the top value if it has been set, else return the max top value */ @@ -78,6 +84,9 @@ static uint32_t mcux_lpc_ctimer_get_top_value(const struct device *dev) } else { return config->info.max_top_value; } +#else + return config->info.max_top_value; +#endif } static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id, @@ -85,11 +94,11 @@ static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id, { const struct mcux_lpc_ctimer_config *config = dev->config; struct mcux_lpc_ctimer_data *data = dev->data; - uint32_t ticks = alarm_cfg->ticks; uint32_t current = mcux_lpc_ctimer_read(config->base); + uint32_t top = mcux_lpc_ctimer_get_top_value(dev); - if (alarm_cfg->ticks > mcux_lpc_ctimer_get_top_value(dev)) { + if (alarm_cfg->ticks > top) { return -EINVAL; } @@ -100,6 +109,9 @@ static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id, if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) { ticks += current; + if (ticks > top) { + ticks %= top; + } } data->channels[chan_id].alarm_callback = alarm_cfg->callback; @@ -136,6 +148,15 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev, const struct mcux_lpc_ctimer_config *config = dev->config; struct mcux_lpc_ctimer_data *data = dev->data; +#ifndef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP + /* Only allow max value when we do not reserve a ctimer channel for setting top value */ + if (cfg->ticks != config->info.max_top_value) { + LOG_ERR("Wrap can only be set to 0x%x", + config->info.max_top_value); + return -ENOTSUP; + } +#endif + data->top_callback = cfg->callback; data->top_user_data = cfg->user_data; @@ -148,6 +169,7 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev, return -ETIME; } +#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP ctimer_match_config_t match_config = { .matchValue = cfg->ticks, .enableCounterReset = true, .enableCounterStop = false, @@ -156,6 +178,7 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev, .enableInterrupt = true }; CTIMER_SetupMatch(config->base, NUM_CHANNELS, &match_config); +#endif return 0; } @@ -216,9 +239,11 @@ static void mcux_lpc_ctimer_isr(const struct device *dev) } } +#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP if (((interrupt_stat & (0x01 << NUM_CHANNELS)) != 0) && data->top_callback) { data->top_callback(dev, data->top_user_data); } +#endif } static int mcux_lpc_ctimer_init(const struct device *dev)