Skip to content

Commit

Permalink
Adds UART RX IRQ Callback with onReceive() (#6134)
Browse files Browse the repository at this point in the history
* Adds UART RX IRQ Callback with onReceive()
  • Loading branch information
SuGlider authored Jan 17, 2022
1 parent 5ae3886 commit c014eaf
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 8 deletions.
5 changes: 5 additions & 0 deletions cores/esp32/HardwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions cores/esp32/HardwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
90 changes: 82 additions & 8 deletions cores/esp32/esp32-hal-uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
};

Expand All @@ -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
};

Expand All @@ -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) {
Expand Down Expand Up @@ -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));

Expand All @@ -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);
Expand All @@ -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();
}

Expand Down
2 changes: 2 additions & 0 deletions cores/esp32/esp32-hal-uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit c014eaf

Please sign in to comment.