Skip to content

Commit 649bb3b

Browse files
mmahadevan108dleach02
authored andcommitted
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 <[email protected]>
1 parent 06cd8ab commit 649bb3b

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

drivers/counter/Kconfig.mcux_ctimer

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,11 @@ config COUNTER_MCUX_CTIMER
88
depends on HAS_MCUX_CTIMER
99
help
1010
Enable support for MCUX CTIMER driver.
11+
12+
config COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
13+
bool "reserve a ctimer channel to set the top value"
14+
default y
15+
depends on COUNTER_MCUX_CTIMER
16+
help
17+
This reserves a CTimer channel to set the top value. Without
18+
this the set top value can be set only to the max counter value.

drivers/counter/counter_mcux_ctimer.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212
#include <zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h>
1313
LOG_MODULE_REGISTER(mcux_ctimer, CONFIG_COUNTER_LOG_LEVEL);
1414

15+
#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
1516
/* One of the CTimer channels is reserved to implement set_top_value API */
1617
#define NUM_CHANNELS 3
18+
#else
19+
#define NUM_CHANNELS 4
20+
#endif
1721

1822
struct mcux_lpc_ctimer_channel_data {
1923
counter_alarm_callback_t alarm_callback;
@@ -70,6 +74,8 @@ static int mcux_lpc_ctimer_get_value(const struct device *dev, uint32_t *ticks)
7074
static uint32_t mcux_lpc_ctimer_get_top_value(const struct device *dev)
7175
{
7276
const struct mcux_lpc_ctimer_config *config = dev->config;
77+
78+
#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
7379
CTIMER_Type *base = config->base;
7480

7581
/* Return the top value if it has been set, else return the max top value */
@@ -78,18 +84,21 @@ static uint32_t mcux_lpc_ctimer_get_top_value(const struct device *dev)
7884
} else {
7985
return config->info.max_top_value;
8086
}
87+
#else
88+
return config->info.max_top_value;
89+
#endif
8190
}
8291

8392
static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id,
8493
const struct counter_alarm_cfg *alarm_cfg)
8594
{
8695
const struct mcux_lpc_ctimer_config *config = dev->config;
8796
struct mcux_lpc_ctimer_data *data = dev->data;
88-
8997
uint32_t ticks = alarm_cfg->ticks;
9098
uint32_t current = mcux_lpc_ctimer_read(config->base);
99+
uint32_t top = mcux_lpc_ctimer_get_top_value(dev);
91100

92-
if (alarm_cfg->ticks > mcux_lpc_ctimer_get_top_value(dev)) {
101+
if (alarm_cfg->ticks > top) {
93102
return -EINVAL;
94103
}
95104

@@ -100,6 +109,9 @@ static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id,
100109

101110
if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) {
102111
ticks += current;
112+
if (ticks > top) {
113+
ticks %= top;
114+
}
103115
}
104116

105117
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,
136148
const struct mcux_lpc_ctimer_config *config = dev->config;
137149
struct mcux_lpc_ctimer_data *data = dev->data;
138150

151+
#ifndef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
152+
/* Only allow max value when we do not reserve a ctimer channel for setting top value */
153+
if (cfg->ticks != config->info.max_top_value) {
154+
LOG_ERR("Wrap can only be set to 0x%x",
155+
config->info.max_top_value);
156+
return -ENOTSUP;
157+
}
158+
#endif
159+
139160
data->top_callback = cfg->callback;
140161
data->top_user_data = cfg->user_data;
141162

@@ -148,6 +169,7 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev,
148169
return -ETIME;
149170
}
150171

172+
#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
151173
ctimer_match_config_t match_config = { .matchValue = cfg->ticks,
152174
.enableCounterReset = true,
153175
.enableCounterStop = false,
@@ -156,6 +178,7 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev,
156178
.enableInterrupt = true };
157179

158180
CTIMER_SetupMatch(config->base, NUM_CHANNELS, &match_config);
181+
#endif
159182

160183
return 0;
161184
}
@@ -216,9 +239,11 @@ static void mcux_lpc_ctimer_isr(const struct device *dev)
216239
}
217240
}
218241

242+
#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
219243
if (((interrupt_stat & (0x01 << NUM_CHANNELS)) != 0) && data->top_callback) {
220244
data->top_callback(dev, data->top_user_data);
221245
}
246+
#endif
222247
}
223248

224249
static int mcux_lpc_ctimer_init(const struct device *dev)

0 commit comments

Comments
 (0)