From 11f9a09bd3d71bac2e8587fdbe137a961ffb38f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Unai=20Uribarri=20Rodr=C3=ADguez?= Date: Sun, 13 May 2018 15:25:14 +0200 Subject: [PATCH] Add UART interrupt dispatcher ESP8266 UART ports share a single interrupt service routine (ISR). This code adds an interrupt dispatcher that allows to define a different ISR for each UART port. --- cores/esp8266/HardwareSerial.h | 10 +++++ cores/esp8266/uart.c | 75 +++++++++++++++++++++++++++------- cores/esp8266/uart.h | 3 ++ 3 files changed, 74 insertions(+), 14 deletions(-) diff --git a/cores/esp8266/HardwareSerial.h b/cores/esp8266/HardwareSerial.h index 0333d4ca87..36f5dd8ce5 100644 --- a/cores/esp8266/HardwareSerial.h +++ b/cores/esp8266/HardwareSerial.h @@ -184,6 +184,16 @@ class HardwareSerial: public Stream return uart_has_overrun(_uart); } + void attachIsr(void (*isr)(void*), void *arg) + { + uart_isr_attach(_uart, isr, arg); + } + + void detachIsr() + { + uart_isr_detach(_uart); + } + protected: int _uart_nr; uart_t* _uart = nullptr; diff --git a/cores/esp8266/uart.c b/cores/esp8266/uart.c index 47814f7a9d..0e57b1c9fd 100644 --- a/cores/esp8266/uart.c +++ b/cores/esp8266/uart.c @@ -240,16 +240,70 @@ uart_resize_rx_buffer(uart_t* uart, size_t new_size) return uart->rx_buffer->size; } +static ets_isr_t s_isr_ptr[2]; +static void * s_isr_arg[2]; +static void ICACHE_RAM_ATTR +uart_isr_dispatcher(void *unused) +{ + (void)unused; + for (int nr = 0; nr < 2; ++nr) + { + if (USIS(nr)) + { + if (s_isr_ptr[nr]) + { + s_isr_ptr[nr](s_isr_arg[nr]); + } + else + { + USIE(nr) = 0; + USIC(nr) = USIS(nr); + } + } + } +} + +void +uart_isr_attach(uart_t* uart, void (*isr)(void*), void *arg) +{ + int nr = uart->uart_nr; + ETS_UART_INTR_DISABLE(); + if (s_isr_ptr[0] == NULL && s_isr_ptr[1] == NULL) + { + ETS_UART_INTR_ATTACH(uart_isr_dispatcher, NULL); + } + s_isr_ptr[nr] = isr; + s_isr_arg[nr] = arg; + ETS_UART_INTR_ENABLE(); +} + +void +uart_isr_detach(uart_t* uart) +{ + int nr = uart->uart_nr; + ETS_UART_INTR_DISABLE(); + s_isr_ptr[nr] = NULL; + s_isr_arg[nr] = NULL; + USIE(nr) = 0; + USIC(nr) = USIS(nr); + if (s_isr_ptr[0] == NULL && s_isr_ptr[1] == NULL) + { + ETS_UART_INTR_ATTACH(NULL, NULL); + } + else + { + ETS_UART_INTR_ENABLE(); + } +} void ICACHE_RAM_ATTR uart_isr(void * arg) { uart_t* uart = (uart_t*)arg; - if(uart == NULL || !uart->rx_enabled) + if(!uart->rx_enabled) { - USIC(uart->uart_nr) = USIS(uart->uart_nr); - ETS_UART_INTR_DISABLE(); + uart_isr_detach(uart); return; } if(USIS(uart->uart_nr) & ((1 << UIFF) | (1 << UITO))) @@ -271,21 +325,15 @@ uart_start_isr(uart_t* uart) USC1(uart->uart_nr) = (100 << UCFFT) | (0x02 << UCTOT) | (1 <uart_nr) = 0xffff; USIE(uart->uart_nr) = (1 << UIFF) | (1 << UIFR) | (1 << UITO); - ETS_UART_INTR_ATTACH(uart_isr, (void *)uart); - ETS_UART_INTR_ENABLE(); + uart_isr_attach(uart, uart_isr, uart); } static void uart_stop_isr(uart_t* uart) { - if(uart == NULL || !uart->rx_enabled) - return; - - ETS_UART_INTR_DISABLE(); - USC1(uart->uart_nr) = 0; - USIC(uart->uart_nr) = 0xffff; - USIE(uart->uart_nr) = 0; - ETS_UART_INTR_ATTACH(NULL, NULL); + uart_isr_detach(uart); + if(uart->rx_enabled) + USC1(uart->uart_nr) = 0; } @@ -527,7 +575,6 @@ uart_uninit(uart_t* uart) if(uart->rx_enabled) { - uart_stop_isr(uart); free(uart->rx_buffer->buffer); free(uart->rx_buffer); } diff --git a/cores/esp8266/uart.h b/cores/esp8266/uart.h index 127c5d0ebb..1d098d4563 100644 --- a/cores/esp8266/uart.h +++ b/cores/esp8266/uart.h @@ -125,6 +125,9 @@ bool uart_rx_enabled(uart_t* uart); void uart_set_baudrate(uart_t* uart, int baud_rate); int uart_get_baudrate(uart_t* uart); +void uart_isr_attach(uart_t* uart, void (*isr)(void*), void *arg); +void uart_isr_detach(uart_t* uart); + size_t uart_resize_rx_buffer(uart_t* uart, size_t new_size); size_t uart_write_char(uart_t* uart, char c);