diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index aed14b19c72..82799ffcfc4 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -159,6 +159,11 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in } } +void HardwareSerial::onReceive(void(*function)(void)) +{ + uartOnReceive(_uart, function); +} + void HardwareSerial::updateBaudRate(unsigned long baud) { uartSetBaudRate(_uart, baud); diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index 40282361bf5..796412c8ce3 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -57,6 +57,10 @@ class HardwareSerial: public Stream public: HardwareSerial(int uart_nr); + // onReceive will setup a callback for whenever UART data is received + // it will work as UART Rx interrupt + void onReceive(void(*function)(void)); + void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL, uint8_t rxfifo_full_thrhd = 112); void end(bool turnOffDebug = true); void updateBaudRate(unsigned long baud); diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index 580c55ddce8..dc22e0dc019 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -34,7 +34,9 @@ struct uart_struct_t { uint8_t num; bool has_peek; uint8_t peek_byte; - + QueueHandle_t uart_event_queue; + void (*onReceive)(void); + TaskHandle_t envent_task; }; #if CONFIG_DISABLE_HAL_LOCKS @@ -43,12 +45,12 @@ struct uart_struct_t { #define UART_MUTEX_UNLOCK() static uart_t _uart_bus_array[] = { - {0, false, 0}, + {0, false, 0, NULL, NULL, NULL}, #if SOC_UART_NUM > 1 - {1, false, 0}, + {1, false, 0, NULL, NULL, NULL}, #endif #if SOC_UART_NUM > 2 - {2, false, 0}, + {2, false, 0, NULL, NULL, NULL}, #endif }; @@ -58,12 +60,12 @@ static uart_t _uart_bus_array[] = { #define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock) static uart_t _uart_bus_array[] = { - {NULL, 0, false, 0}, + {NULL, 0, false, 0, NULL, NULL, NULL}, #if SOC_UART_NUM > 1 - {NULL, 1, false, 0}, + {NULL, 1, false, 0, NULL, NULL, NULL}, #endif #if SOC_UART_NUM > 2 - {NULL, 2, false, 0}, + {NULL, 2, false, 0, NULL, NULL, NULL}, #endif }; @@ -82,6 +84,67 @@ uint32_t _get_effective_baudrate(uint32_t baudrate) } } + +void uartOnReceive(uart_t* uart, void(*function)(void)) +{ + if(uart == NULL || function == NULL) { + return; + } + UART_MUTEX_LOCK(); + uart->onReceive = function; + UART_MUTEX_UNLOCK(); +} + + +static void uart_event_task(void *args) +{ + uart_t* uart = (uart_t *)args; + uart_event_t event; + for(;;) { + //Waiting for UART event. + if(xQueueReceive(uart->uart_event_queue, (void * )&event, (portTickType)portMAX_DELAY)) { + switch(event.type) { + //Event of UART receving data + case UART_DATA: + UART_MUTEX_LOCK(); + if(uart->onReceive) uart->onReceive(); + UART_MUTEX_UNLOCK(); + break; + //Event of HW FIFO overflow detected + case UART_FIFO_OVF: + log_w("UART%d FIFO Overflow. Flushing data. Consider adding Flow Control to your Application.", uart->num); + uart_flush_input(uart->num); + xQueueReset(uart->uart_event_queue); + break; + //Event of UART ring buffer full + case UART_BUFFER_FULL: + log_w("UART%d Buffer Full. Flushing data. Consider encreasing your buffer size of your Application.", uart->num); + uart_flush_input(uart->num); + xQueueReset(uart->uart_event_queue); + break; + //Event of UART RX break detected + case UART_BREAK: + log_w("UART%d RX break.", uart->num); + break; + //Event of UART parity check error + case UART_PARITY_ERR: + log_w("UART%d parity error.", uart->num); + break; + //Event of UART frame error + case UART_FRAME_ERR: + log_w("UART%d frame error.", uart->num); + break; + //Others + default: + log_w("UART%d unknown event type %d.", uart->num, event.type); + break; + } + } + } + vTaskDelete(NULL); +} + + bool uartIsDriverInstalled(uart_t* uart) { if(uart == NULL) { @@ -143,7 +206,7 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx uart_config.source_clk = UART_SCLK_APB; - ESP_ERROR_CHECK(uart_driver_install(uart_nr, 2*queueLen, 0, 0, NULL, 0)); + ESP_ERROR_CHECK(uart_driver_install(uart_nr, 2*queueLen, 0, 20, &(uart->uart_event_queue), 0)); ESP_ERROR_CHECK(uart_param_config(uart_nr, &uart_config)); ESP_ERROR_CHECK(uart_set_pin(uart_nr, txPin, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); @@ -153,6 +216,12 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx ESP_ERROR_CHECK(uart_set_line_inverse(uart_nr, UART_SIGNAL_TXD_INV | UART_SIGNAL_RXD_INV)); } + // Creating UART event Task + xTaskCreate(uart_event_task, "uart_event_task", 2048, uart, configMAX_PRIORITIES - 1, &(uart->envent_task)); + if (!uart->envent_task) { + log_e(" -- UART%d Event Task not Created!", uart_nr); + } + UART_MUTEX_UNLOCK(); uartFlush(uart); @@ -167,6 +236,11 @@ void uartEnd(uart_t* uart) UART_MUTEX_LOCK(); uart_driver_delete(uart->num); + if (uart->envent_task) { + vTaskDelete(uart->envent_task); + uart->envent_task = NULL; + uart->onReceive = NULL; + } UART_MUTEX_UNLOCK(); } diff --git a/cores/esp32/esp32-hal-uart.h b/cores/esp32/esp32-hal-uart.h index 609f380f59e..ff790bf6691 100644 --- a/cores/esp32/esp32-hal-uart.h +++ b/cores/esp32/esp32-hal-uart.h @@ -54,6 +54,8 @@ typedef struct uart_struct_t uart_t; uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted, uint8_t rxfifo_full_thrhd); void uartEnd(uart_t* uart); +void uartOnReceive(uart_t* uart, void(*function)(void)); + uint32_t uartAvailable(uart_t* uart); uint32_t uartAvailableForWrite(uart_t* uart); uint8_t uartRead(uart_t* uart);