Skip to content

Commit

Permalink
drivers: counter: Update CTimer to fix alarm setting
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
mmahadevan108 authored and dleach02 committed May 23, 2022
1 parent 06cd8ab commit 649bb3b
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 2 deletions.
8 changes: 8 additions & 0 deletions drivers/counter/Kconfig.mcux_ctimer
Original file line number Diff line number Diff line change
Expand Up @@ -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.
29 changes: 27 additions & 2 deletions drivers/counter/counter_mcux_ctimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@
#include <zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h>
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;
Expand Down Expand Up @@ -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 */
Expand All @@ -78,18 +84,21 @@ 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,
const struct counter_alarm_cfg *alarm_cfg)
{
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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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,
Expand All @@ -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;
}
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 649bb3b

Please sign in to comment.