Skip to content

Commit 65473e8

Browse files
sylvioalveskartben
authored andcommitted
drivers: counter: esp32: add top value handling
Implements top value callback and handling. Signed-off-by: Sylvio Alves <[email protected]>
1 parent dca598e commit 65473e8

File tree

1 file changed

+77
-13
lines changed

1 file changed

+77
-13
lines changed

drivers/counter/counter_esp32_tmr.c

Lines changed: 77 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ static void counter_esp32_isr(void *arg);
2424

2525
typedef bool (*timer_isr_t)(void *);
2626

27-
struct timer_isr_func_t {
28-
timer_isr_t fn;
29-
void *args;
30-
struct intr_handle_data_t *timer_isr_handle;
31-
timer_group_t isr_timer_group;
27+
struct counter_esp32_top_data {
28+
counter_top_callback_t callback;
29+
uint32_t ticks;
30+
void *user_data;
31+
bool auto_reload;
3232
};
3333

3434
struct counter_esp32_config {
@@ -45,10 +45,10 @@ struct counter_esp32_config {
4545

4646
struct counter_esp32_data {
4747
struct counter_alarm_cfg alarm_cfg;
48+
struct counter_esp32_top_data top_data;
4849
uint32_t ticks;
4950
uint32_t clock_src_hz;
5051
timer_hal_context_t hal_ctx;
51-
struct timer_isr_func_t timer_isr_fun;
5252
};
5353

5454
static int counter_esp32_init(const struct device *dev)
@@ -65,8 +65,13 @@ static int counter_esp32_init(const struct device *dev)
6565
*/
6666
clock_control_on(cfg->clock_dev, cfg->clock_subsys);
6767

68-
timer_hal_init(&data->hal_ctx, cfg->group, cfg->index);
6968
data->alarm_cfg.callback = NULL;
69+
data->top_data.callback = NULL;
70+
data->top_data.user_data = NULL;
71+
data->top_data.auto_reload = false;
72+
data->top_data.ticks = cfg->counter_info.max_top_value;
73+
74+
timer_hal_init(&data->hal_ctx, cfg->group, cfg->index);
7075
timer_ll_enable_intr(data->hal_ctx.dev, TIMER_LL_EVENT_ALARM(data->hal_ctx.timer_id),
7176
false);
7277
timer_ll_clear_intr_status(data->hal_ctx.dev, TIMER_LL_EVENT_ALARM(data->hal_ctx.timer_id));
@@ -139,11 +144,20 @@ static int counter_esp32_set_alarm(const struct device *dev, uint8_t chan_id,
139144
{
140145
ARG_UNUSED(chan_id);
141146
struct counter_esp32_data *data = dev->data;
147+
uint32_t ticks = alarm_cfg->ticks;
142148
uint32_t now;
143149

150+
if (ticks > data->top_data.ticks) {
151+
return -EINVAL;
152+
}
153+
144154
counter_esp32_get_value(dev, &now);
145155

146156
if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) {
157+
ticks += now;
158+
if (ticks > data->top_data.ticks) {
159+
ticks -= (data->top_data.ticks + 1);
160+
}
147161
timer_ll_set_alarm_value(data->hal_ctx.dev, data->hal_ctx.timer_id,
148162
(now + alarm_cfg->ticks));
149163
} else {
@@ -163,23 +177,59 @@ static int counter_esp32_cancel_alarm(const struct device *dev, uint8_t chan_id)
163177
{
164178
ARG_UNUSED(chan_id);
165179
struct counter_esp32_data *data = dev->data;
166-
167180
timer_ll_enable_intr(data->hal_ctx.dev, TIMER_LL_EVENT_ALARM(data->hal_ctx.timer_id),
168181
false);
169182
timer_ll_enable_alarm(data->hal_ctx.dev, data->hal_ctx.timer_id, TIMER_ALARM_DIS);
183+
timer_ll_clear_intr_status(data->hal_ctx.dev, TIMER_LL_EVENT_ALARM(data->hal_ctx.timer_id));
184+
185+
data->alarm_cfg.callback = NULL;
186+
data->alarm_cfg.user_data = NULL;
170187

171188
return 0;
172189
}
173190

174191
static int counter_esp32_set_top_value(const struct device *dev, const struct counter_top_cfg *cfg)
175192
{
176193
const struct counter_esp32_config *config = dev->config;
194+
struct counter_esp32_data *data = dev->data;
195+
uint32_t now;
177196

178-
if (cfg->ticks != config->counter_info.max_top_value) {
197+
if (data->alarm_cfg.callback) {
198+
return -EBUSY;
199+
}
200+
201+
if (cfg->ticks > config->counter_info.max_top_value) {
179202
return -ENOTSUP;
203+
}
204+
205+
counter_esp32_get_value(dev, &now);
206+
207+
if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
208+
timer_hal_set_counter_value(&data->hal_ctx, 0);
180209
} else {
181-
return 0;
210+
if (now > cfg->ticks) {
211+
if (cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) {
212+
timer_hal_set_counter_value(&data->hal_ctx, 0);
213+
} else {
214+
return -ETIME;
215+
}
216+
}
182217
}
218+
219+
data->top_data.ticks = cfg->ticks;
220+
data->top_data.callback = cfg->callback;
221+
data->top_data.user_data = cfg->user_data;
222+
data->top_data.auto_reload = (cfg->callback != NULL);
223+
224+
timer_ll_clear_intr_status(data->hal_ctx.dev, TIMER_LL_EVENT_ALARM(data->hal_ctx.timer_id));
225+
timer_ll_set_alarm_value(data->hal_ctx.dev, data->hal_ctx.timer_id, cfg->ticks);
226+
timer_ll_enable_intr(data->hal_ctx.dev, TIMER_LL_EVENT_ALARM(data->hal_ctx.timer_id), true);
227+
timer_ll_enable_alarm(data->hal_ctx.dev, data->hal_ctx.timer_id, TIMER_ALARM_EN);
228+
229+
timer_ll_enable_auto_reload(data->hal_ctx.dev, data->hal_ctx.timer_id,
230+
cfg->callback ? TIMER_AUTORELOAD_EN : TIMER_AUTORELOAD_DIS);
231+
232+
return 0;
183233
}
184234

185235
static uint32_t counter_esp32_get_pending_int(const struct device *dev)
@@ -191,9 +241,9 @@ static uint32_t counter_esp32_get_pending_int(const struct device *dev)
191241

192242
static uint32_t counter_esp32_get_top_value(const struct device *dev)
193243
{
194-
const struct counter_esp32_config *config = dev->config;
244+
struct counter_esp32_data *data = dev->data;
195245

196-
return config->counter_info.max_top_value;
246+
return data->top_data.ticks;
197247
}
198248

199249
uint32_t counter_esp32_get_freq(const struct device *dev)
@@ -233,11 +283,25 @@ static void counter_esp32_isr(void *arg)
233283
struct counter_esp32_data *data = dev->data;
234284
uint32_t now;
235285

236-
counter_esp32_cancel_alarm(dev, 0);
237286
counter_esp32_get_value(dev, &now);
238287

239288
if (data->alarm_cfg.callback) {
240289
data->alarm_cfg.callback(dev, 0, now, data->alarm_cfg.user_data);
290+
timer_ll_enable_intr(data->hal_ctx.dev,
291+
TIMER_LL_EVENT_ALARM(data->hal_ctx.timer_id), false);
292+
timer_ll_enable_alarm(data->hal_ctx.dev, data->hal_ctx.timer_id, TIMER_ALARM_DIS);
293+
data->alarm_cfg.callback = NULL;
294+
data->alarm_cfg.user_data = NULL;
295+
}
296+
297+
if (data->top_data.callback) {
298+
data->top_data.callback(dev, data->top_data.user_data);
299+
if (data->top_data.auto_reload) {
300+
timer_ll_enable_intr(data->hal_ctx.dev,
301+
TIMER_LL_EVENT_ALARM(data->hal_ctx.timer_id), true);
302+
timer_ll_enable_alarm(data->hal_ctx.dev, data->hal_ctx.timer_id,
303+
TIMER_ALARM_EN);
304+
}
241305
}
242306

243307
timer_ll_clear_intr_status(data->hal_ctx.dev, TIMER_LL_EVENT_ALARM(data->hal_ctx.timer_id));

0 commit comments

Comments
 (0)