summaryrefslogtreecommitdiffstatshomepage
path: root/ports/esp32/machine_uart.c
diff options
context:
space:
mode:
Diffstat (limited to 'ports/esp32/machine_uart.c')
-rw-r--r--ports/esp32/machine_uart.c74
1 files changed, 42 insertions, 32 deletions
diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c
index 73089ef463..982d9a7e27 100644
--- a/ports/esp32/machine_uart.c
+++ b/ports/esp32/machine_uart.c
@@ -59,6 +59,7 @@
#define UART_IRQ_BREAK (1 << UART_BREAK)
#define MP_UART_ALLOWED_FLAGS (UART_IRQ_RX | UART_IRQ_RXIDLE | UART_IRQ_BREAK)
#define RXIDLE_TIMER_MIN (5000) // 500 us
+#define UART_QUEUE_SIZE (3)
enum {
RXIDLE_INACTIVE,
@@ -109,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);
}
}
@@ -149,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;
@@ -174,6 +162,13 @@ static void uart_event_task(void *self_in) {
}
}
+static inline void uart_event_task_create(machine_uart_obj_t *self) {
+ if (xTaskCreatePinnedToCore(uart_event_task, "uart_event_task", 2048, self,
+ ESP_TASKD_EVENT_PRIO, (TaskHandle_t *)&self->uart_event_task, MP_TASK_COREID) != pdPASS) {
+ mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("failed to create UART event task"));
+ }
+}
+
static void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint32_t baudrate;
@@ -250,7 +245,7 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
// wait for all data to be transmitted before changing settings
uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000));
- if (args[ARG_txbuf].u_int >= 0 || args[ARG_rxbuf].u_int >= 0) {
+ if ((args[ARG_txbuf].u_int >= 0 && args[ARG_txbuf].u_int != self->txbuf) || (args[ARG_rxbuf].u_int >= 0 && args[ARG_rxbuf].u_int != self->rxbuf)) {
// must reinitialise driver to change the tx/rx buffer size
#if MICROPY_HW_ENABLE_UART_REPL
if (self->uart_num == MICROPY_HW_UART_REPL) {
@@ -275,9 +270,12 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
check_esp_err(uart_get_word_length(self->uart_num, &uartcfg.data_bits));
check_esp_err(uart_get_parity(self->uart_num, &uartcfg.parity));
check_esp_err(uart_get_stop_bits(self->uart_num, &uartcfg.stop_bits));
- check_esp_err(uart_driver_delete(self->uart_num));
+ mp_machine_uart_deinit(self);
check_esp_err(uart_param_config(self->uart_num, &uartcfg));
- check_esp_err(uart_driver_install(self->uart_num, self->rxbuf, self->txbuf, 0, NULL, 0));
+ check_esp_err(uart_driver_install(self->uart_num, self->rxbuf, self->txbuf, UART_QUEUE_SIZE, &self->uart_queue, 0));
+ if (self->mp_irq_obj != NULL && self->mp_irq_obj->handler != mp_const_none) {
+ uart_event_task_create(self);
+ }
}
// set baudrate
@@ -437,7 +435,8 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
self->timeout_char = 0;
self->invert = 0;
self->flowcontrol = 0;
- self->uart_event_task = 0;
+ self->uart_event_task = NULL;
+ self->uart_queue = NULL;
self->rxidle_state = RXIDLE_INACTIVE;
switch (uart_num) {
@@ -470,12 +469,13 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
{
// Remove any existing configuration
check_esp_err(uart_driver_delete(self->uart_num));
+ self->uart_queue = NULL;
// init the peripheral
// Setup
check_esp_err(uart_param_config(self->uart_num, &uartcfg));
- check_esp_err(uart_driver_install(uart_num, self->rxbuf, self->txbuf, 3, &self->uart_queue, 0));
+ check_esp_err(uart_driver_install(uart_num, self->rxbuf, self->txbuf, UART_QUEUE_SIZE, &self->uart_queue, 0));
}
mp_map_t kw_args;
@@ -489,7 +489,12 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
}
static void mp_machine_uart_deinit(machine_uart_obj_t *self) {
+ if (self->uart_event_task != NULL) {
+ vTaskDelete(self->uart_event_task);
+ self->uart_event_task = NULL;
+ }
check_esp_err(uart_driver_delete(self->uart_num));
+ self->uart_queue = NULL;
}
static mp_int_t mp_machine_uart_any(machine_uart_obj_t *self) {
@@ -535,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;
}
}
@@ -568,6 +573,12 @@ static const mp_irq_methods_t uart_irq_methods = {
};
static mp_irq_obj_t *mp_machine_uart_irq(machine_uart_obj_t *self, bool any_args, mp_arg_val_t *args) {
+ #if MICROPY_HW_ENABLE_UART_REPL
+ if (self->uart_num == MICROPY_HW_UART_REPL) {
+ mp_raise_ValueError(MP_ERROR_TEXT("UART does not support IRQs"));
+ }
+ #endif
+
if (self->mp_irq_obj == NULL) {
self->mp_irq_trigger = 0;
self->mp_irq_obj = mp_irq_new(&uart_irq_methods, MP_OBJ_FROM_PTR(self));
@@ -597,9 +608,8 @@ static mp_irq_obj_t *mp_machine_uart_irq(machine_uart_obj_t *self, bool any_args
uart_irq_configure_timer(self, trigger);
// Start a task for handling events
- if (handler != mp_const_none && self->uart_event_task == NULL) {
- xTaskCreatePinnedToCore(uart_event_task, "uart_event_task", 2048, self,
- ESP_TASKD_EVENT_PRIO, (TaskHandle_t *)&self->uart_event_task, MP_TASK_COREID);
+ if (handler != mp_const_none && self->uart_event_task == NULL && self->uart_queue != NULL) {
+ uart_event_task_create(self);
} else if (handler == mp_const_none && self->uart_event_task != NULL) {
vTaskDelete(self->uart_event_task);
self->uart_event_task = NULL;