#define UART_FULL_THRESH_DEFAULT (120)
#define UART_TOUT_THRESH_DEFAULT (10)
#define UART_TX_IDLE_NUM_DEFAULT (0)
+#define UART_PATTERN_DET_QLEN_DEFAULT (10)
+
#define UART_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux)
#define UART_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux)
#define UART_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)
} tx_data;
} uart_tx_data_t;
+typedef struct {
+ int wr;
+ int rd;
+ int len;
+ int* data;
+} uart_pat_rb_t;
+
typedef struct {
uart_port_t uart_num; /*!< UART port number*/
int queue_size; /*!< UART event queue size*/
uint8_t* rx_head_ptr; /*!< pointer to the head of RX item*/
uint8_t rx_data_buf[UART_FIFO_LEN]; /*!< Data buffer to stash FIFO data*/
uint8_t rx_stash_len; /*!< stashed data length.(When using flow control, after reading out FIFO data, if we fail to push to buffer, we can just stash them.) */
+ uart_pat_rb_t rx_pattern_pos;
+
//tx parameters
SemaphoreHandle_t tx_fifo_sem; /*!< UART TX FIFO semaphore*/
SemaphoreHandle_t tx_mux; /*!< UART TX mutex*/
uint8_t tx_waiting_brk; /*!< Flag to indicate that TX FIFO is ready to send break signal after FIFO is empty, do not push data into TX FIFO right now.*/
} uart_obj_t;
-
-
static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0};
/* DRAM_ATTR is required to avoid UART array placed in flash, due to accessed from ISR */
static DRAM_ATTR uart_dev_t* const UART[UART_NUM_MAX] = {&UART0, &UART1, &UART2};
static esp_err_t uart_reset_rx_fifo(uart_port_t uart_num)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
- // Read all data from the FIFO
- while (UART[uart_num]->status.rxfifo_cnt) {
+ //Due to hardware issue, we can not use fifo_rst to reset uart fifo.
+ //See description about UART_TXFIFO_RST and UART_RXFIFO_RST in <<esp32_technical_reference_manual>> v2.6 or later.
+
+ // we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`.
+ while(UART[uart_num]->status.rxfifo_cnt != 0 || (UART[uart_num]->mem_rx_status.wr_addr != UART[uart_num]->mem_rx_status.rd_addr)) {
READ_PERI_REG(UART_FIFO_REG(uart_num));
}
return ESP_OK;
return ESP_OK;
}
+static esp_err_t uart_pattern_link_free(uart_port_t uart_num)
+{
+ UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);
+ if (p_uart_obj[uart_num]->rx_pattern_pos.data != NULL) {
+ int* pdata = p_uart_obj[uart_num]->rx_pattern_pos.data;
+ UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+ p_uart_obj[uart_num]->rx_pattern_pos.data = NULL;
+ p_uart_obj[uart_num]->rx_pattern_pos.wr = 0;
+ p_uart_obj[uart_num]->rx_pattern_pos.rd = 0;
+ UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+ free(pdata);
+ }
+ return ESP_OK;
+}
+
+static esp_err_t uart_pattern_enqueue(uart_port_t uart_num, int pos)
+{
+ UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);
+ esp_err_t ret = ESP_OK;
+ UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+ uart_pat_rb_t* p_pos = &p_uart_obj[uart_num]->rx_pattern_pos;
+ int next = p_pos->wr + 1;
+ if (next >= p_pos->len) {
+ next = 0;
+ }
+ if (next == p_pos->rd) {
+ ESP_EARLY_LOGW(UART_TAG, "Fail to enqueue pattern position, pattern queue is full.");
+ ret = ESP_FAIL;
+ } else {
+ p_pos->data[p_pos->wr] = pos;
+ p_pos->wr = next;
+ ret = ESP_OK;
+ }
+ UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+ return ret;
+}
+
+static esp_err_t uart_pattern_dequeue(uart_port_t uart_num)
+{
+ UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);
+ if(p_uart_obj[uart_num]->rx_pattern_pos.data == NULL) {
+ return ESP_ERR_INVALID_STATE;
+ } else {
+ esp_err_t ret = ESP_OK;
+ UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+ uart_pat_rb_t* p_pos = &p_uart_obj[uart_num]->rx_pattern_pos;
+ if (p_pos->rd == p_pos->wr) {
+ ret = ESP_FAIL;
+ } else {
+ p_pos->rd++;
+ }
+ if (p_pos->rd >= p_pos->len) {
+ p_pos->rd = 0;
+ }
+ UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+ return ret;
+ }
+}
+
+static esp_err_t uart_pattern_queue_update(uart_port_t uart_num, int diff_len)
+{
+ UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);
+ UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+ uart_pat_rb_t* p_pos = &p_uart_obj[uart_num]->rx_pattern_pos;
+ int rd = p_pos->rd;
+ while(rd != p_pos->wr) {
+ p_pos->data[rd] -= diff_len;
+ int rd_rec = rd;
+ rd ++;
+ if (rd >= p_pos->len) {
+ rd = 0;
+ }
+ if (p_pos->data[rd_rec] < 0) {
+ p_pos->rd = rd;
+ }
+ }
+ UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+ return ESP_OK;
+}
+
+int uart_pattern_pop_pos(uart_port_t uart_num)
+{
+ UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1));
+ UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+ uart_pat_rb_t* pat_pos = &p_uart_obj[uart_num]->rx_pattern_pos;
+ int pos = -1;
+ if (pat_pos != NULL && pat_pos->rd != pat_pos->wr) {
+ pos = pat_pos->data[pat_pos->rd];
+ uart_pattern_dequeue(uart_num);
+ }
+ UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+ return pos;
+}
+
+esp_err_t uart_pattern_queue_reset(uart_port_t uart_num, int queue_length)
+{
+ UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
+ UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_ERR_INVALID_STATE);
+
+ int* pdata = (int*) malloc(queue_length * sizeof(int));
+ if(pdata == NULL) {
+ return ESP_ERR_NO_MEM;
+ }
+ UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+ int* ptmp = p_uart_obj[uart_num]->rx_pattern_pos.data;
+ p_uart_obj[uart_num]->rx_pattern_pos.data = pdata;
+ p_uart_obj[uart_num]->rx_pattern_pos.len = queue_length;
+ p_uart_obj[uart_num]->rx_pattern_pos.rd = 0;
+ p_uart_obj[uart_num]->rx_pattern_pos.wr = 0;
+ UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
+ free(ptmp);
+ return ESP_OK;
+}
+
esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
return ESP_OK;
}
+static int uart_find_pattern_from_last(uint8_t* buf, int length, uint8_t pat_chr, int pat_num)
+{
+ int cnt = 0;
+ int len = length;
+ while (len >= 0) {
+ if (buf[len] == pat_chr) {
+ cnt++;
+ } else {
+ cnt = 0;
+ }
+ if (cnt >= pat_num) {
+ break;
+ }
+ len --;
+ }
+ return len;
+}
+
//internal isr handler for default driver code.
static void uart_rx_intr_handler_default(void *param)
{
uart_obj_t *p_uart = (uart_obj_t*) param;
uint8_t uart_num = p_uart->uart_num;
uart_dev_t* uart_reg = UART[uart_num];
+ int rx_fifo_len = uart_reg->status.rxfifo_cnt;
uint8_t buf_idx = 0;
uint32_t uart_intr_status = UART[uart_num]->int_st.val;
- int rx_fifo_len = 0;
uart_event_t uart_event;
portBASE_TYPE HPTaskAwoken = 0;
-
+ static uint8_t pat_flg = 0;
while(uart_intr_status != 0x0) {
buf_idx = 0;
uart_event.type = UART_EVENT_MAX;
if(uart_intr_status & UART_TXFIFO_EMPTY_INT_ST_M) {
- UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
- uart_reg->int_ena.txfifo_empty = 0;
- uart_reg->int_clr.txfifo_empty = 1;
- UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+ uart_clear_intr_status(uart_num, UART_TXFIFO_EMPTY_INT_CLR_M);
+ uart_disable_intr_mask(uart_num, UART_TXFIFO_EMPTY_INT_ENA_M);
if(p_uart->tx_waiting_brk) {
continue;
}
if(HPTaskAwoken == pdTRUE) {
portYIELD_FROM_ISR() ;
}
- }
- else {
+ } else {
//We don't use TX ring buffer, because the size is zero.
if(p_uart->tx_buf_size == 0) {
continue;
break;
}
}
- if(p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) {
+ if (p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) {
//To fill the TX FIFO.
int send_len = p_uart->tx_len_cur > tx_fifo_rem ? tx_fifo_rem : p_uart->tx_len_cur;
for(buf_idx = 0; buf_idx < send_len; buf_idx++) {
p_uart->tx_len_tot -= send_len;
p_uart->tx_len_cur -= send_len;
tx_fifo_rem -= send_len;
- if(p_uart->tx_len_cur == 0) {
+ if (p_uart->tx_len_cur == 0) {
//Return item to ring buffer.
vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken);
if(HPTaskAwoken == pdTRUE) {
}
}
}
- if(en_tx_flg) {
- UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
- uart_reg->int_clr.txfifo_empty = 1;
- uart_reg->int_ena.txfifo_empty = 1;
- UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+ if (en_tx_flg) {
+ uart_clear_intr_status(uart_num, UART_TXFIFO_EMPTY_INT_CLR_M);
+ uart_enable_intr_mask(uart_num, UART_TXFIFO_EMPTY_INT_ENA_M);
}
}
}
- else if((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M) || (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)) {
- if(p_uart->rx_buffer_full_flg == false) {
- //Get the buffer from the FIFO
- rx_fifo_len = uart_reg->status.rxfifo_cnt;
- p_uart->rx_stash_len = rx_fifo_len;
+ else if ((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M)
+ || (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)
+ || (uart_intr_status & UART_AT_CMD_CHAR_DET_INT_ST_M)
+ ) {
+ rx_fifo_len = uart_reg->status.rxfifo_cnt;
+ if(pat_flg == 1) {
+ uart_intr_status |= UART_AT_CMD_CHAR_DET_INT_ST_M;
+ pat_flg = 0;
+ }
+ if (p_uart->rx_buffer_full_flg == false) {
//We have to read out all data in RX FIFO to clear the interrupt signal
- while(buf_idx < rx_fifo_len) {
+ while (buf_idx < rx_fifo_len) {
p_uart->rx_data_buf[buf_idx++] = uart_reg->fifo.rw_byte;
}
- //After Copying the Data From FIFO ,Clear intr_status
- UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
- uart_reg->int_clr.rxfifo_tout = 1;
- uart_reg->int_clr.rxfifo_full = 1;
- UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
- uart_event.size = rx_fifo_len;
+ uint8_t pat_chr = uart_reg->at_cmd_char.data;
+ int pat_num = uart_reg->at_cmd_char.char_num;
+ int pat_idx = -1;
+
+ //Get the buffer from the FIFO
+ if (uart_intr_status & UART_AT_CMD_CHAR_DET_INT_ST_M) {
+ uart_clear_intr_status(uart_num, UART_AT_CMD_CHAR_DET_INT_CLR_M);
+ uart_event.type = UART_PATTERN_DET;
+ uart_event.size = rx_fifo_len;
+ pat_idx = uart_find_pattern_from_last(p_uart->rx_data_buf, rx_fifo_len - 1, pat_chr, pat_num);
+ } else {
+ //After Copying the Data From FIFO ,Clear intr_status
+ uart_clear_intr_status(uart_num, UART_RXFIFO_TOUT_INT_CLR_M | UART_RXFIFO_FULL_INT_CLR_M);
+ uart_event.type = UART_DATA;
+ uart_event.size = rx_fifo_len;
+ }
+ p_uart->rx_stash_len = rx_fifo_len;
//If we fail to push data to ring buffer, we will have to stash the data, and send next time.
//Mainly for applications that uses flow control or small ring buffer.
if(pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->rx_data_buf, p_uart->rx_stash_len, &HPTaskAwoken)) {
- UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
- uart_reg->int_ena.rxfifo_full = 0;
- uart_reg->int_ena.rxfifo_tout = 0;
- UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
- p_uart->rx_buffer_full_flg = true;
+ uart_disable_intr_mask(uart_num, UART_RXFIFO_TOUT_INT_ENA_M | UART_RXFIFO_FULL_INT_ENA_M);
+ if (uart_event.type == UART_PATTERN_DET) {
+ if (rx_fifo_len < pat_num) {
+ //some of the characters are read out in last interrupt
+ uart_pattern_enqueue(uart_num, p_uart->rx_buffered_len - (pat_num - rx_fifo_len));
+ } else {
+ uart_pattern_enqueue(uart_num,
+ pat_idx <= -1 ?
+ //can not find the pattern in buffer,
+ p_uart->rx_buffered_len + p_uart->rx_stash_len :
+ // find the pattern in buffer
+ p_uart->rx_buffered_len + pat_idx);
+ }
+ if ((p_uart->xQueueUart != NULL) && (pdFALSE == xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken))) {
+ ESP_EARLY_LOGW(UART_TAG, "UART event queue full");
+ }
+ }
uart_event.type = UART_BUFFER_FULL;
+ p_uart->rx_buffer_full_flg = true;
} else {
UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
+ if (uart_intr_status & UART_AT_CMD_CHAR_DET_INT_ST_M) {
+ if (rx_fifo_len < pat_num) {
+ //some of the characters are read out in last interrupt
+ uart_pattern_enqueue(uart_num, p_uart->rx_buffered_len - (pat_num - rx_fifo_len));
+ } else if(pat_idx >= 0) {
+ // find pattern in statsh buffer.
+ uart_pattern_enqueue(uart_num, p_uart->rx_buffered_len + pat_idx);
+ }
+ }
p_uart->rx_buffered_len += p_uart->rx_stash_len;
UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
- uart_event.type = UART_DATA;
}
if(HPTaskAwoken == pdTRUE) {
portYIELD_FROM_ISR() ;
}
} else {
- UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
- uart_reg->int_ena.rxfifo_full = 0;
- uart_reg->int_ena.rxfifo_tout = 0;
- uart_reg->int_clr.val = UART_RXFIFO_FULL_INT_CLR_M | UART_RXFIFO_TOUT_INT_CLR_M;
- UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
- uart_event.type = UART_BUFFER_FULL;
+ uart_disable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M);
+ uart_clear_intr_status(uart_num, UART_RXFIFO_FULL_INT_CLR_M | UART_RXFIFO_TOUT_INT_CLR_M);
+ if(uart_intr_status & UART_AT_CMD_CHAR_DET_INT_ST_M) {
+ uart_reg->int_clr.at_cmd_char_det = 1;
+ uart_event.type = UART_PATTERN_DET;
+ uart_event.size = rx_fifo_len;
+ pat_flg = 1;
+ }
}
} else if(uart_intr_status & UART_RXFIFO_OVF_INT_ST_M) {
+ // When fifo overflows, we reset the fifo.
UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
- // Read all data from the FIFO
- rx_fifo_len = uart_reg->status.rxfifo_cnt;
- for (int i = 0; i < rx_fifo_len; i++) {
- READ_PERI_REG(UART_FIFO_REG(uart_num));
- }
+ uart_reset_rx_fifo(uart_num);
uart_reg->int_clr.rxfifo_ovf = 1;
UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
uart_event.type = UART_FIFO_OVF;
}
}
} else if(uart_intr_status & UART_TX_BRK_IDLE_DONE_INT_ST_M) {
- UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
- uart_reg->int_ena.tx_brk_idle_done = 0;
- uart_reg->int_clr.tx_brk_idle_done = 1;
- UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+ uart_disable_intr_mask(uart_num, UART_TX_BRK_IDLE_DONE_INT_ENA_M);
+ uart_clear_intr_status(uart_num, UART_TX_BRK_IDLE_DONE_INT_CLR_M);
} else if(uart_intr_status & UART_AT_CMD_CHAR_DET_INT_ST_M) {
uart_reg->int_clr.at_cmd_char_det = 1;
uart_event.type = UART_PATTERN_DET;
} else if(uart_intr_status & UART_TX_DONE_INT_ST_M) {
- UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
- uart_reg->int_ena.tx_done = 0;
- uart_reg->int_clr.tx_done = 1;
- UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
+ uart_disable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M);
+ uart_clear_intr_status(uart_num, UART_TX_DONE_INT_CLR_M);
xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);
if(HPTaskAwoken == pdTRUE) {
portYIELD_FROM_ISR() ;
}
if(uart_event.type != UART_EVENT_MAX && p_uart->xQueueUart) {
- xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken);
+ if (pdFALSE == xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken)) {
+ ESP_EARLY_LOGW(UART_TAG, "UART event queue full");
+ }
if(HPTaskAwoken == pdTRUE) {
portYIELD_FROM_ISR() ;
}
offset += send_size;
uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT);
}
- xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
} else {
while(size) {
//semaphore for tx_fifo available
p_uart_obj[uart_num]->rx_cur_remain = size;
} else {
xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);
- UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
- p_uart_obj[uart_num]->rx_buffered_len -= copy_len;
- UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
return copy_len;
}
}
len_tmp = p_uart_obj[uart_num]->rx_cur_remain;
}
memcpy(buf + copy_len, p_uart_obj[uart_num]->rx_ptr, len_tmp);
+ UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
+ p_uart_obj[uart_num]->rx_buffered_len -= len_tmp;
+ uart_pattern_queue_update(uart_num, len_tmp);
p_uart_obj[uart_num]->rx_ptr += len_tmp;
+ UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
p_uart_obj[uart_num]->rx_cur_remain -= len_tmp;
copy_len += len_tmp;
length -= len_tmp;
}
}
}
+
xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);
- UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
- p_uart_obj[uart_num]->rx_buffered_len -= copy_len;
- UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
return copy_len;
}
return ESP_OK;
}
-esp_err_t uart_flush(uart_port_t uart_num)
+esp_err_t uart_flush(uart_port_t uart_num) __attribute__((alias("uart_flush_input")));
+
+esp_err_t uart_flush_input(uart_port_t uart_num)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);
vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->rx_head_ptr);
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
p_uart_obj[uart_num]->rx_buffered_len -= p_uart->rx_cur_remain;
+ uart_pattern_queue_update(uart_num, p_uart->rx_cur_remain);
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
p_uart->rx_ptr = NULL;
p_uart->rx_cur_remain = 0;
}
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
p_uart_obj[uart_num]->rx_buffered_len -= size;
+ uart_pattern_queue_update(uart_num, size);
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
vRingbufferReturnItem(p_uart->rx_ring_buf, data);
if(p_uart_obj[uart_num]->rx_buffer_full_flg) {
UART_CHECK((intr_alloc_flags & ESP_INTR_FLAG_IRAM) == 0, "ESP_INTR_FLAG_IRAM set in intr_alloc_flags", ESP_FAIL); /* uart_rx_intr_handler_default is not in IRAM */
if(p_uart_obj[uart_num] == NULL) {
- p_uart_obj[uart_num] = (uart_obj_t*) malloc(sizeof(uart_obj_t));
+ p_uart_obj[uart_num] = (uart_obj_t*) calloc(1, sizeof(uart_obj_t));
if(p_uart_obj[uart_num] == NULL) {
ESP_LOGE(UART_TAG, "UART driver malloc error");
return ESP_FAIL;
p_uart_obj[uart_num]->tx_brk_len = 0;
p_uart_obj[uart_num]->tx_waiting_brk = 0;
p_uart_obj[uart_num]->rx_buffered_len = 0;
+ uart_pattern_queue_reset(uart_num, UART_PATTERN_DET_QLEN_DEFAULT);
if(uart_queue) {
p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t));
esp_intr_free(p_uart_obj[uart_num]->intr_handle);
uart_disable_rx_intr(uart_num);
uart_disable_tx_intr(uart_num);
+ uart_pattern_link_free(uart_num);
if(p_uart_obj[uart_num]->tx_fifo_sem) {
vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem);
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
+#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
*/
#define EX_UART_NUM UART_NUM_0
+#define PATTERN_CHR_NUM (3) /*!< Set the number of consecutive and identical characters received by receiver which defines a UART pattern*/
#define BUF_SIZE (1024)
+#define RD_BUF_SIZE (BUF_SIZE)
static QueueHandle_t uart0_queue;
static void uart_event_task(void *pvParameters)
{
uart_event_t event;
size_t buffered_size;
- uint8_t *dtmp = (uint8_t *) malloc(BUF_SIZE);
- while (1) {
- /* Waiting for UART event.
- If it happens then print out information what is it */
- if (xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
+ uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE);
+ for(;;) {
+ //Waiting for UART event.
+ if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
+ bzero(dtmp, RD_BUF_SIZE);
ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM);
- switch (event.type) {
- case UART_DATA:
- /* Event of UART receiving data
- * We'd better handler data event fast, there would be much more data events
- * than other types of events.
- * If we take too much time on data event, the queue might be full.
- * In this example, we don't process data in event, but read data outside.
- */
- uart_get_buffered_data_len(EX_UART_NUM, &buffered_size);
- ESP_LOGI(TAG, "data, len: %d; buffered len: %d", event.size, buffered_size);
- break;
- case UART_FIFO_OVF:
- ESP_LOGE(TAG, "hw fifo overflow");
- // If fifo overflow happened, you should consider adding flow control for your application.
- // We can read data out out the buffer, or directly flush the Rx buffer.
- uart_flush(EX_UART_NUM);
- break;
- case UART_BUFFER_FULL:
- ESP_LOGE(TAG, "ring buffer full");
- // If buffer full happened, you should consider increasing your buffer size
- // We can read data out out the buffer, or directly flush the Rx buffer.
- uart_flush(EX_UART_NUM);
- break;
- case UART_BREAK:
- ESP_LOGI(TAG, "uart rx break detected");
- break;
- case UART_PARITY_ERR:
- ESP_LOGE(TAG, "uart parity error");
- break;
- case UART_FRAME_ERR:
- ESP_LOGE(TAG, "uart frame error");
- break;
- case UART_PATTERN_DET:
- ESP_LOGI(TAG, "uart pattern detected");
- break;
- default:
- ESP_LOGE(TAG, "not serviced uart event type: %d\n", event.type);
- break;
+ switch(event.type) {
+ //Event of UART receving data
+ /*We'd better handler data event fast, there would be much more data events than
+ other types of events. If we take too much time on data event, the queue might
+ be full.*/
+ case UART_DATA:
+ ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
+ uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);
+ ESP_LOGI(TAG, "[DATA EVT]:");
+ uart_write_bytes(EX_UART_NUM, (const char*) dtmp, event.size);
+ break;
+ //Event of HW FIFO overflow detected
+ case UART_FIFO_OVF:
+ ESP_LOGI(TAG, "hw fifo overflow");
+ // If fifo overflow happened, you should consider adding flow control for your application.
+ // The ISR has already reset the rx FIFO,
+ // As an example, we directly flush the rx buffer here in order to read more data.
+ uart_flush_input(EX_UART_NUM);
+ xQueueReset(uart0_queue);
+ break;
+ //Event of UART ring buffer full
+ case UART_BUFFER_FULL:
+ ESP_LOGI(TAG, "ring buffer full");
+ // If buffer full happened, you should consider encreasing your buffer size
+ // As an example, we directly flush the rx buffer here in order to read more data.
+ uart_flush_input(EX_UART_NUM);
+ xQueueReset(uart0_queue);
+ break;
+ //Event of UART RX break detected
+ case UART_BREAK:
+ ESP_LOGI(TAG, "uart rx break");
+ break;
+ //Event of UART parity check error
+ case UART_PARITY_ERR:
+ ESP_LOGI(TAG, "uart parity error");
+ break;
+ //Event of UART frame error
+ case UART_FRAME_ERR:
+ ESP_LOGI(TAG, "uart frame error");
+ break;
+ //UART_PATTERN_DET
+ case UART_PATTERN_DET:
+ uart_get_buffered_data_len(EX_UART_NUM, &buffered_size);
+ int pos = uart_pattern_pop_pos(EX_UART_NUM);
+ ESP_LOGI(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", pos, buffered_size);
+ if (pos == -1) {
+ // There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not
+ // record the position. We should set a larger queue size.
+ // As an example, we directly flush the rx buffer here.
+ uart_flush_input(EX_UART_NUM);
+ } else {
+ uart_read_bytes(EX_UART_NUM, dtmp, pos, 100 / portTICK_PERIOD_MS);
+ uint8_t pat[PATTERN_CHR_NUM + 1];
+ memset(pat, 0, sizeof(pat));
+ uart_read_bytes(EX_UART_NUM, pat, PATTERN_CHR_NUM, 100 / portTICK_PERIOD_MS);
+ ESP_LOGI(TAG, "read data: %s", dtmp);
+ ESP_LOGI(TAG, "read pat : %s", pat);
+ }
+ break;
+ //Others
+ default:
+ ESP_LOGI(TAG, "uart event type: %d", event.type);
+ break;
}
}
}
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(EX_UART_NUM, &uart_config);
- // Set UART pins using UART0 default pins i.e. no changes
+
+ //Set UART log level
+ esp_log_level_set(TAG, ESP_LOG_INFO);
+ //Set UART pins (using UART0 default pins ie no changes.)
uart_set_pin(EX_UART_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
- uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 10, &uart0_queue, 0);
+ //Install UART driver, and get the queue.
+ uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
- // Set uart pattern detection function
- uart_enable_pattern_det_intr(EX_UART_NUM, '+', 3, 10000, 10, 10);
+ //Set uart pattern detect function.
+ uart_enable_pattern_det_intr(EX_UART_NUM, '+', PATTERN_CHR_NUM, 10000, 10, 10);
+ //Reset the pattern queue length to record at most 20 pattern positions.
+ uart_pattern_queue_reset(EX_UART_NUM, 20);
- // Create a task to handle uart event from ISR
+ //Create a task to handler UART event from ISR
xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 12, NULL);
-
- // Reserve a buffer and process incoming data
- uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
- while (1) {
- int len = uart_read_bytes(EX_UART_NUM, data, BUF_SIZE, 100 / portTICK_RATE_MS);
- if (len > 0) {
- ESP_LOGI(TAG, "uart read : %d", len);
- uart_write_bytes(EX_UART_NUM, (const char *)data, len);
- }
- }
}