Skip to content

Adds UART RX IRQ Callback with onReceive() #6134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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