mirror of
https://github.com/micropython/micropython.git
synced 2025-07-21 21:11:12 +02:00
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>
This commit is contained in:
committed by
Damien George
parent
bf909303ff
commit
2c2f0b292a
@@ -151,12 +151,16 @@ static void machine_timer_isr(void *self_in) {
|
||||
if (self->repeat) {
|
||||
timer_ll_enable_alarm(self->hal_context.dev, self->index, true);
|
||||
}
|
||||
mp_sched_schedule(self->callback, self);
|
||||
mp_hal_wake_main_task_from_isr();
|
||||
self->handler(self);
|
||||
}
|
||||
}
|
||||
|
||||
void machine_timer_enable(machine_timer_obj_t *self, void (*timer_isr)) {
|
||||
static void machine_timer_isr_handler(machine_timer_obj_t *self) {
|
||||
mp_sched_schedule(self->callback, self);
|
||||
mp_hal_wake_main_task_from_isr();
|
||||
}
|
||||
|
||||
void machine_timer_enable(machine_timer_obj_t *self) {
|
||||
// Initialise the timer.
|
||||
timer_hal_init(&self->hal_context, self->group, self->index);
|
||||
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)) {
|
||||
timer_ll_enable_intr(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index), false);
|
||||
timer_ll_clear_intr_status(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index));
|
||||
if (self->handle) {
|
||||
ESP_ERROR_CHECK(esp_intr_free(self->handle));
|
||||
self->handle = NULL;
|
||||
ESP_ERROR_CHECK(esp_intr_enable(self->handle));
|
||||
} else {
|
||||
ESP_ERROR_CHECK(esp_intr_alloc(
|
||||
timer_group_periph_signals.groups[self->group].timer_irq_id[self->index],
|
||||
TIMER_FLAGS,
|
||||
machine_timer_isr,
|
||||
self,
|
||||
&self->handle
|
||||
));
|
||||
}
|
||||
ESP_ERROR_CHECK(
|
||||
esp_intr_alloc(timer_group_periph_signals.groups[self->group].timer_irq_id[self->index],
|
||||
TIMER_FLAGS, timer_isr, self, &self->handle)
|
||||
);
|
||||
timer_ll_enable_intr(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index), true);
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
self->repeat = args[ARG_mode].u_int;
|
||||
self->handler = machine_timer_isr_handler;
|
||||
self->callback = args[ARG_callback].u_obj;
|
||||
self->handle = NULL;
|
||||
|
||||
machine_timer_enable(self, machine_timer_isr);
|
||||
machine_timer_enable(self);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
@@ -55,12 +55,13 @@ typedef struct _machine_timer_obj_t {
|
||||
mp_obj_t callback;
|
||||
|
||||
intr_handle_t handle;
|
||||
void (*handler)(struct _machine_timer_obj_t *timer);
|
||||
|
||||
struct _machine_timer_obj_t *next;
|
||||
} machine_timer_obj_t;
|
||||
|
||||
machine_timer_obj_t *machine_timer_create(mp_uint_t timer);
|
||||
void machine_timer_enable(machine_timer_obj_t *self, void (*timer_isr));
|
||||
void machine_timer_enable(machine_timer_obj_t *self);
|
||||
void machine_timer_disable(machine_timer_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_ESP32_MACHINE_TIMER_H
|
||||
|
@@ -110,30 +110,19 @@ static const char *_parity_name[] = {"None", "1", "0"};
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_RXIDLE), MP_ROM_INT(UART_IRQ_RXIDLE) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_BREAK), MP_ROM_INT(UART_IRQ_BREAK) }, \
|
||||
|
||||
static void uart_timer_callback(void *self_in) {
|
||||
machine_timer_obj_t *self = self_in;
|
||||
|
||||
uint32_t intr_status = timer_ll_get_intr_status(self->hal_context.dev);
|
||||
|
||||
if (intr_status & TIMER_LL_EVENT_ALARM(self->index)) {
|
||||
timer_ll_clear_intr_status(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index));
|
||||
if (self->repeat) {
|
||||
timer_ll_enable_alarm(self->hal_context.dev, self->index, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void uart_timer_callback(machine_timer_obj_t *timer) {
|
||||
// The UART object is referred here by the callback field.
|
||||
machine_uart_obj_t *uart = (machine_uart_obj_t *)self->callback;
|
||||
if (uart->rxidle_state == RXIDLE_ALERT) {
|
||||
machine_uart_obj_t *self = (machine_uart_obj_t *)timer->callback;
|
||||
if (self->rxidle_state == RXIDLE_ALERT) {
|
||||
// At the first call, just switch the state
|
||||
uart->rxidle_state = RXIDLE_ARMED;
|
||||
} else if (uart->rxidle_state == RXIDLE_ARMED) {
|
||||
self->rxidle_state = RXIDLE_ARMED;
|
||||
} else if (self->rxidle_state == RXIDLE_ARMED) {
|
||||
// At the second call, run the irq callback and stop the timer
|
||||
uart->rxidle_state = RXIDLE_STANDBY;
|
||||
uart->mp_irq_flags = UART_IRQ_RXIDLE;
|
||||
mp_irq_handler(uart->mp_irq_obj);
|
||||
self->rxidle_state = RXIDLE_STANDBY;
|
||||
self->mp_irq_flags = UART_IRQ_RXIDLE;
|
||||
mp_irq_handler(self->mp_irq_obj);
|
||||
mp_hal_wake_main_task_from_isr();
|
||||
machine_timer_disable(uart->rxidle_timer);
|
||||
machine_timer_disable(self->rxidle_timer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,9 +139,7 @@ static void uart_event_task(void *self_in) {
|
||||
if (self->mp_irq_trigger & UART_IRQ_RXIDLE) {
|
||||
if (self->rxidle_state != RXIDLE_INACTIVE) {
|
||||
if (self->rxidle_state == RXIDLE_STANDBY) {
|
||||
self->rxidle_timer->repeat = true;
|
||||
self->rxidle_timer->handle = NULL;
|
||||
machine_timer_enable(self->rxidle_timer, uart_timer_callback);
|
||||
machine_timer_enable(self->rxidle_timer);
|
||||
}
|
||||
}
|
||||
self->rxidle_state = RXIDLE_ALERT;
|
||||
@@ -553,11 +540,11 @@ static void uart_irq_configure_timer(machine_uart_obj_t *self, mp_uint_t trigger
|
||||
}
|
||||
self->rxidle_period = period;
|
||||
self->rxidle_timer->period = period;
|
||||
self->rxidle_timer->handler = uart_timer_callback;
|
||||
// The Python callback is not used. So use this
|
||||
// data field to hold a reference to the UART object.
|
||||
self->rxidle_timer->callback = self;
|
||||
self->rxidle_timer->repeat = true;
|
||||
self->rxidle_timer->handle = NULL;
|
||||
self->rxidle_state = RXIDLE_STANDBY;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user