Skip to content

Commit 2e0fb59

Browse files
committed
esp32: Re-use allocated timer interrupts and simplify UART timer code.
If the interrupt is not freed but merely disabled, instead of reallocating it every time the timer is enabled again we can instead just re-enable it. That means we're no longer setting the handler every time, and we need to ensure it does not change. Doing so by adding an additional wrapper function does not only solve that problem, it also allows us to remove some code duplication and simplify how machine_uart uses the timer. Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
1 parent f99cd07 commit 2e0fb59

File tree

3 files changed

+31
-36
lines changed

3 files changed

+31
-36
lines changed

ports/esp32/machine_timer.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,16 @@ static void machine_timer_isr(void *self_in) {
151151
if (self->repeat) {
152152
timer_ll_enable_alarm(self->hal_context.dev, self->index, true);
153153
}
154-
mp_sched_schedule(self->callback, self);
155-
mp_hal_wake_main_task_from_isr();
154+
self->handler(self);
156155
}
157156
}
158157

159-
void machine_timer_enable(machine_timer_obj_t *self, void (*timer_isr)) {
158+
static void machine_timer_isr_handler(machine_timer_obj_t *self) {
159+
mp_sched_schedule(self->callback, self);
160+
mp_hal_wake_main_task_from_isr();
161+
}
162+
163+
void machine_timer_enable(machine_timer_obj_t *self) {
160164
// Initialise the timer.
161165
timer_hal_init(&self->hal_context, self->group, self->index);
162166
timer_ll_enable_counter(self->hal_context.dev, self->index, false);
@@ -169,13 +173,16 @@ void machine_timer_enable(machine_timer_obj_t *self, void (*timer_isr)) {
169173
timer_ll_enable_intr(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index), false);
170174
timer_ll_clear_intr_status(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index));
171175
if (self->handle) {
172-
ESP_ERROR_CHECK(esp_intr_free(self->handle));
173-
self->handle = NULL;
176+
ESP_ERROR_CHECK(esp_intr_enable(self->handle));
177+
} else {
178+
ESP_ERROR_CHECK(esp_intr_alloc(
179+
timer_group_periph_signals.groups[self->group].timer_irq_id[self->index],
180+
TIMER_FLAGS,
181+
machine_timer_isr,
182+
self,
183+
&self->handle
184+
));
174185
}
175-
ESP_ERROR_CHECK(
176-
esp_intr_alloc(timer_group_periph_signals.groups[self->group].timer_irq_id[self->index],
177-
TIMER_FLAGS, timer_isr, self, &self->handle)
178-
);
179186
timer_ll_enable_intr(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index), true);
180187

181188
// Enable the alarm to trigger at the given period.
@@ -229,10 +236,10 @@ static mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n
229236
}
230237

231238
self->repeat = args[ARG_mode].u_int;
239+
self->handler = machine_timer_isr_handler;
232240
self->callback = args[ARG_callback].u_obj;
233-
self->handle = NULL;
234241

235-
machine_timer_enable(self, machine_timer_isr);
242+
machine_timer_enable(self);
236243

237244
return mp_const_none;
238245
}

ports/esp32/machine_timer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,13 @@ typedef struct _machine_timer_obj_t {
5555
mp_obj_t callback;
5656

5757
intr_handle_t handle;
58+
void (*handler)(struct _machine_timer_obj_t *timer);
5859

5960
struct _machine_timer_obj_t *next;
6061
} machine_timer_obj_t;
6162

6263
machine_timer_obj_t *machine_timer_create(mp_uint_t timer);
63-
void machine_timer_enable(machine_timer_obj_t *self, void (*timer_isr));
64+
void machine_timer_enable(machine_timer_obj_t *self);
6465
void machine_timer_disable(machine_timer_obj_t *self);
6566

6667
#endif // MICROPY_INCLUDED_ESP32_MACHINE_TIMER_H

ports/esp32/machine_uart.c

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -109,30 +109,19 @@ static const char *_parity_name[] = {"None", "1", "0"};
109109
{ MP_ROM_QSTR(MP_QSTR_IRQ_RXIDLE), MP_ROM_INT(UART_IRQ_RXIDLE) }, \
110110
{ MP_ROM_QSTR(MP_QSTR_IRQ_BREAK), MP_ROM_INT(UART_IRQ_BREAK) }, \
111111

112-
static void uart_timer_callback(void *self_in) {
113-
machine_timer_obj_t *self = self_in;
114-
115-
uint32_t intr_status = timer_ll_get_intr_status(self->hal_context.dev);
116-
117-
if (intr_status & TIMER_LL_EVENT_ALARM(self->index)) {
118-
timer_ll_clear_intr_status(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index));
119-
if (self->repeat) {
120-
timer_ll_enable_alarm(self->hal_context.dev, self->index, true);
121-
}
122-
}
123-
112+
static void uart_timer_callback(machine_timer_obj_t *timer) {
124113
// The UART object is referred here by the callback field.
125-
machine_uart_obj_t *uart = (machine_uart_obj_t *)self->callback;
126-
if (uart->rxidle_state == RXIDLE_ALERT) {
114+
machine_uart_obj_t *self = (machine_uart_obj_t *)timer->callback;
115+
if (self->rxidle_state == RXIDLE_ALERT) {
127116
// At the first call, just switch the state
128-
uart->rxidle_state = RXIDLE_ARMED;
129-
} else if (uart->rxidle_state == RXIDLE_ARMED) {
117+
self->rxidle_state = RXIDLE_ARMED;
118+
} else if (self->rxidle_state == RXIDLE_ARMED) {
130119
// At the second call, run the irq callback and stop the timer
131-
uart->rxidle_state = RXIDLE_STANDBY;
132-
uart->mp_irq_flags = UART_IRQ_RXIDLE;
133-
mp_irq_handler(uart->mp_irq_obj);
120+
self->rxidle_state = RXIDLE_STANDBY;
121+
self->mp_irq_flags = UART_IRQ_RXIDLE;
122+
mp_irq_handler(self->mp_irq_obj);
134123
mp_hal_wake_main_task_from_isr();
135-
machine_timer_disable(uart->rxidle_timer);
124+
machine_timer_disable(self->rxidle_timer);
136125
}
137126
}
138127

@@ -149,9 +138,7 @@ static void uart_event_task(void *self_in) {
149138
if (self->mp_irq_trigger & UART_IRQ_RXIDLE) {
150139
if (self->rxidle_state != RXIDLE_INACTIVE) {
151140
if (self->rxidle_state == RXIDLE_STANDBY) {
152-
self->rxidle_timer->repeat = true;
153-
self->rxidle_timer->handle = NULL;
154-
machine_timer_enable(self->rxidle_timer, uart_timer_callback);
141+
machine_timer_enable(self->rxidle_timer);
155142
}
156143
}
157144
self->rxidle_state = RXIDLE_ALERT;
@@ -535,11 +522,11 @@ static void uart_irq_configure_timer(machine_uart_obj_t *self, mp_uint_t trigger
535522
}
536523
self->rxidle_period = period;
537524
self->rxidle_timer->period = period;
525+
self->rxidle_timer->handler = uart_timer_callback;
538526
// The Python callback is not used. So use this
539527
// data field to hold a reference to the UART object.
540528
self->rxidle_timer->callback = self;
541529
self->rxidle_timer->repeat = true;
542-
self->rxidle_timer->handle = NULL;
543530
self->rxidle_state = RXIDLE_STANDBY;
544531
}
545532
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy