From 9ed7c4f8bc7f0c8d1f26bf68877b95099b6703ef Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Thu, 3 Nov 2016 23:30:54 +0800 Subject: [PATCH] fix ringbuffer bug. --- components/driver/include/driver/uart.h | 3 +- components/driver/uart.c | 427 ++++++++++++------------ components/freertos/ringbuf.c | 30 +- 3 files changed, 214 insertions(+), 246 deletions(-) diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index 445d71b685..0d9ab3c563 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -437,13 +437,12 @@ esp_err_t uart_intr_config(uart_port_t uart_num, uart_intr_config_t *p_intr_conf * @param queue_size UART event queue size/depth. * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details * @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue. - * @param buf_type UART RX ring_buffer type * * @return * - ESP_OK Success * - ESP_FAIL Parameter error */ -esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue, ringbuf_type_t rx_buf_type); +esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue); /** * @brief Uninstall UART driver. diff --git a/components/driver/uart.c b/components/driver/uart.c index d6585405f2..9eaf783438 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -43,28 +43,35 @@ const char* UART_TAG = "UART"; #define UART_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) typedef struct { - uart_port_t uart_num; - SemaphoreHandle_t tx_fifo_sem; - SemaphoreHandle_t tx_mutex; - SemaphoreHandle_t tx_buffer_mutex; - SemaphoreHandle_t tx_done_sem; - SemaphoreHandle_t tx_brk_sem; - SemaphoreHandle_t rx_mux; - QueueHandle_t xQueueUart; - int queue_size; - int intr_num; - int rx_buf_size; - ringbuf_type_t rx_buf_type; - RingbufHandle_t rx_ring_buf; - int tx_buf_size; - RingbufHandle_t tx_ring_buf; - bool buffer_full_flg; - bool tx_waiting; - int cur_remain; - uint8_t* rd_ptr; - uint8_t* head_ptr; - uint8_t data_buf[UART_FIFO_LEN]; - uint8_t data_len; + uart_port_t uart_num; /*!< UART port number*/ + int queue_size; /*!< UART event queue size*/ + QueueHandle_t xQueueUart; /*!< UART queue handler*/ + int intr_num; /*!< UART interrupt number*/ + //rx parameters + SemaphoreHandle_t rx_mux; /*!< UART RX data mutex*/ + int rx_buf_size; /*!< RX ring buffer size */ + RingbufHandle_t rx_ring_buf; /*!< RX ring buffer handler*/ + bool rx_buffer_full_flg; /*!< RX ring buffer full flag. */ + int rx_cur_remain; /*!< Data number that waiting to be read out in ring buffer item*/ + uint8_t* rx_ptr; /*!< pointer to the current data in ring buffer*/ + 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.) */ + //tx parameters + SemaphoreHandle_t tx_fifo_sem; /*!< UART TX FIFO semaphore*/ + SemaphoreHandle_t tx_mux; /*!< UART TX mutex*/ + SemaphoreHandle_t tx_buffer_mux; /*!< UART TX buffer semaphore*/ + SemaphoreHandle_t tx_done_sem; /*!< UART TX done semaphore*/ + SemaphoreHandle_t tx_brk_sem; /*!< UART TX send break done semaphore*/ + int tx_buf_size; /*!< TX ring buffer size */ + RingbufHandle_t tx_ring_buf; /*!< TX ring buffer handler*/ + bool tx_waiting_fifo; /*!< this flag indicates that some task is waiting for FIFO empty interrupt, used to send all data without any data buffer*/ + uint8_t* tx_ptr; /*!< TX data pointer to push to FIFO in TX buffer mode*/ + uart_event_t* tx_head; /*!< TX data pointer to head of the current buffer in TX ring buffer*/ + uint32_t tx_len_tot; /*!< Total length of current item in ring buffer*/ + uint8_t tx_brk_flg; /*!< Flag to indicate to send a break signal in the end of the item sending procedure */ + uint8_t tx_brk_len; /*!< TX break signal cycle length/number */ + 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}; @@ -438,16 +445,8 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uint32_t uart_intr_status = UART[uart_num]->int_st.val; int rx_fifo_len = 0; uart_event_t uart_event; - - static uint8_t * tx_ptr; - static uart_event_t* tx_head; - static int tx_len_tot = 0; - static int brk_flg = 0; - static int tx_brk_len = 0; - static int wait_brk = 0; - - portBASE_TYPE HPTaskAwoken = 0; + while(uart_intr_status != 0x0) { buf_idx = 0; uart_event.type = UART_EVENT_MAX; @@ -456,85 +455,92 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_reg->int_ena.txfifo_empty = 0; uart_reg->int_clr.txfifo_empty = 1; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); - if(wait_brk) { + if(p_uart->tx_waiting_brk) { return; } - if(p_uart->tx_waiting == true) { - p_uart->tx_waiting = false; + if(p_uart->tx_waiting_fifo == true) { + p_uart->tx_waiting_fifo = false; xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, NULL); } else { + //We don't use TX ring buffer, because the size if zero. + if(p_uart->tx_buf_size == 0) { + return; + } int tx_fifo_rem = UART_FIFO_LEN - UART[uart_num]->status.txfifo_cnt; bool en_tx_flg = false; - if(tx_len_tot == 0) { - size_t size; -// ets_printf("dbg1,tot=0,get 1st head\n"); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); - tx_head = (uart_event_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); - if(tx_head) { //enable empty intr -// tx_ptr = (uint8_t*)tx_head + sizeof(uart_event_t); - tx_ptr = NULL; -// en_tx_flg = true; - tx_len_tot = tx_head->data.size; - if(tx_head->type == UART_DATA_BREAK) { - tx_len_tot = tx_head->data.size; - brk_flg = 1; - tx_brk_len = tx_head->data.brk_len; + //We need to put a loop here, in case all the buffer items are very short. + //That would cause a watch_dog reset because empty interrupt happens so often. + //Although this is a loop in ISR, this loop will execute at most 128 turns. + while(tx_fifo_rem) { + if(p_uart->tx_len_tot == 0) { + size_t size; + //The first item is the data description + //Get the first item to get the data information + p_uart->tx_head = (uart_event_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); + if(p_uart->tx_head) { + p_uart->tx_ptr = NULL; + p_uart->tx_len_tot = p_uart->tx_head->data.size; + if(p_uart->tx_head->type == UART_DATA_BREAK) { + p_uart->tx_len_tot = p_uart->tx_head->data.size; + p_uart->tx_brk_flg = 1; + p_uart->tx_brk_len = p_uart->tx_head->data.brk_len; + } + //We have saved the data description from the 1st item, return buffer. + vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); + } + else { + //Can not get data from ring buffer, return; + return; } -// ets_printf("ret1,tot: %d\n", tx_len_tot); - vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, tx_head, &HPTaskAwoken); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); } - else { - return; - } - } - if(tx_ptr == NULL) { - size_t size; -// ets_printf("dbg2, tx ptr null, get 2nd tx ptr\n"); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); - tx_ptr = (uint8_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); - -// xRingbufferPrintInfo(p_uart->tx_ring_buf); - if(tx_ptr) { - tx_head = (void*) tx_ptr; -// ets_printf("get size: %d ; h size: %d\n", size, tx_len_tot); - en_tx_flg = true; - } else { - return; - } - } -// else - if(tx_len_tot > 0 && tx_ptr) { //tx - int send_len = tx_len_tot > tx_fifo_rem ? tx_fifo_rem : tx_len_tot; - for(buf_idx = 0; buf_idx < send_len; buf_idx++) { - WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), *(tx_ptr++) & 0xff); - } - tx_len_tot -= send_len; -// ets_printf("tot: %d\n", tx_len_tot); - if(tx_len_tot == 0) { - if(brk_flg == 1) { - UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); - uart_reg->int_ena.tx_brk_done = 0; - uart_reg->idle_conf.tx_brk_num = tx_brk_len; - uart_reg->conf0.txd_brk = 1; - uart_reg->int_clr.tx_brk_done = 1; - uart_reg->int_ena.tx_brk_done = 1; - UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); - wait_brk = 1; + if(p_uart->tx_ptr == NULL) { + size_t size; + //2nd item is the data we need to send through UART + //Get 2nd item from ring buffer + p_uart->tx_ptr = (uint8_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); + if(p_uart->tx_ptr) { + //Update the TX item head, we will need this to return item to buffer. + p_uart->tx_head = (void*) p_uart->tx_ptr; + en_tx_flg = true; } else { + //Can not get data from ring buffer, return; + return; + } + } + if(p_uart->tx_len_tot > 0 && p_uart->tx_ptr) { + //To fill the TX FIFO. + int send_len = p_uart->tx_len_tot > tx_fifo_rem ? tx_fifo_rem : p_uart->tx_len_tot; + for(buf_idx = 0; buf_idx < send_len; buf_idx++) { + WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), *(p_uart->tx_ptr++) & 0xff); + } + p_uart->tx_len_tot -= send_len; + tx_fifo_rem -= send_len; + if(p_uart->tx_len_tot == 0) { + //Sending item done, now we need to send break if there is a record. + //Return item to ring buffer. + vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); + p_uart->tx_head = NULL; + p_uart->tx_ptr = NULL; + //Set TX break signal after FIFO is empty + if(p_uart->tx_brk_flg == 1) { + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->int_ena.tx_brk_done = 0; + uart_reg->idle_conf.tx_brk_num = p_uart->tx_brk_len; + uart_reg->conf0.txd_brk = 1; + uart_reg->int_clr.tx_brk_done = 1; + uart_reg->int_ena.tx_brk_done = 1; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + p_uart->tx_waiting_brk = 1; + return; + } else { + //enable TX empty interrupt + en_tx_flg = true; + } + } else { + //enable TX empty interrupt en_tx_flg = true; } -// ets_printf("ret2\n"); - vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, tx_head, &HPTaskAwoken); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); - tx_head = NULL; - tx_ptr = NULL; - } else { - en_tx_flg = true; } } if(en_tx_flg) { @@ -546,14 +552,13 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) } } else if((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M) || (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)) { - if(p_uart->buffer_full_flg == false) { + if(p_uart->rx_buffer_full_flg == false) { //Get the buffer from the FIFO -// ESP_LOGE(UART_TAG, "FULL\n"); rx_fifo_len = uart_reg->status.rxfifo_cnt; - p_uart->data_len = rx_fifo_len; - memset(p_uart->data_buf, 0, sizeof(p_uart->data_buf)); + p_uart->rx_stash_len = rx_fifo_len; + //We have to read out all data in RX FIFO to clear the interrupt signal while(buf_idx < rx_fifo_len) { - p_uart->data_buf[buf_idx++] = uart_reg->fifo.rw_byte; + 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]); @@ -562,12 +567,14 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_event.type = UART_DATA; uart_event.data.size = rx_fifo_len; - if(pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->data_buf, p_uart->data_len, &HPTaskAwoken)) { + //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->buffer_full_flg = true; + p_uart->rx_buffer_full_flg = true; uart_event.type = UART_BUFFER_FULL; } else { uart_event.type = UART_DATA; @@ -597,19 +604,17 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_reg->int_clr.frm_err = 1; uart_event.type = UART_PARITY_ERR; } else if(uart_intr_status & UART_TX_BRK_DONE_INT_ST_M) { -// ESP_LOGE(UART_TAG, "UART TX BRK DONE\n"); - ets_printf("tx brk done\n"); UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_reg->conf0.txd_brk = 0; uart_reg->int_ena.tx_brk_done = 0; uart_reg->int_clr.tx_brk_done = 1; - if(brk_flg == 1) { + if(p_uart->tx_brk_flg == 1) { uart_reg->int_ena.txfifo_empty = 1; } UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); - if(brk_flg == 1) { - brk_flg = 0; - wait_brk = 0; + if(p_uart->tx_brk_flg == 1) { + p_uart->tx_brk_flg = 0; + p_uart->tx_waiting_brk = 0; } else { xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken); } @@ -644,8 +649,8 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); BaseType_t res; portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; - //Take tx_mutex - res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mutex, (portTickType)ticks_to_wait); + //Take tx_mux + res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait); if(res == pdFALSE) { return ESP_ERR_TIMEOUT; } @@ -653,7 +658,7 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, 0); ticks_to_wait = ticks_end - xTaskGetTickCount(); if(UART[uart_num]->status.txfifo_cnt == 0) { - xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return ESP_OK; } uart_enable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M); @@ -661,10 +666,10 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) res = xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, (portTickType)ticks_to_wait); if(res == pdFALSE) { uart_disable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M); - xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return ESP_ERR_TIMEOUT; } - xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return ESP_OK; } @@ -701,9 +706,9 @@ int uart_tx_chars(uart_port_t uart_num, char* buffer, uint32_t len) if(len == 0) { return 0; } - xSemaphoreTake(p_uart_obj[uart_num]->tx_mutex, (portTickType)portMAX_DELAY); + xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); int tx_len = uart_fill_fifo(uart_num, buffer, len); - xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return tx_len; } @@ -716,14 +721,14 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool return 0; } //lock for uart_tx - xSemaphoreTake(p_uart_obj[uart_num]->tx_mutex, (portTickType)portMAX_DELAY); + xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); size_t original_size = size; while(size) { //semaphore for tx_fifo available if(pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) { size_t sent = uart_fill_fifo(uart_num, (char*) src, size); if(sent < size) { - p_uart_obj[uart_num]->tx_waiting = true; + p_uart_obj[uart_num]->tx_waiting_fifo = true; uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); } size -= sent; @@ -735,49 +740,25 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool xSemaphoreTake(p_uart_obj[uart_num]->tx_brk_sem, (portTickType)portMAX_DELAY); } xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); - xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return original_size; } -//static void uart_tx_task(void* arg) -//{ -// uart_obj_t* p_uart = (uart_obj_t*) arg; -// size_t size; -// uart_event_t evt; -// for(;;) { -// char* data = (char*) xRingbufferReceive(p_uart->tx_ring_buf, &size, portMAX_DELAY); -// if(data == NULL) { -// continue; -// } -// memcpy(&evt, data, sizeof(evt)); -// if(evt.type == UART_DATA) { -// uart_tx_all(p_uart->uart_num, (const char*) data + sizeof(uart_event_t), evt.data.size, 0, 0); -// } else if(evt.type == UART_DATA_BREAK) { -// uart_tx_all(p_uart->uart_num, (const char*) data + sizeof(uart_event_t), evt.data.size, 1, evt.data.brk_len); -// } -// vRingbufferReturnItem(p_uart->tx_ring_buf, data); -// } -// vTaskDelete(NULL); -//} - int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); UART_CHECK((p_uart_obj[uart_num] != NULL), "uart driver error"); UART_CHECK(src, "buffer null"); + //Push data to TX ring buffer and return, ISR will send the data. if(p_uart_obj[uart_num]->tx_buf_size > 0) { if(xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf) > (size + sizeof(uart_event_t))) { uart_event_t evt; - xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mutex, (portTickType)portMAX_DELAY); + xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mux, (portTickType)portMAX_DELAY); evt.type = UART_DATA; evt.data.size = size; - ets_printf("-----1st send-----\n"); xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); - xRingbufferPrintInfo(p_uart_obj[uart_num]->tx_ring_buf); - ets_printf("====2nd send====\n"); xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) src, size, portMAX_DELAY); - xRingbufferPrintInfo(p_uart_obj[uart_num]->tx_ring_buf); - xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mux); uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); return size; } else { @@ -785,6 +766,7 @@ int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) return uart_tx_all(uart_num, src, size, 0, 0); } } else { + //Send data without TX ring buffer, the task will block until all data have been sent out return uart_tx_all(uart_num, src, size, 0, 0); } } @@ -796,16 +778,17 @@ int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t s UART_CHECK((size > 0), "uart size error"); UART_CHECK((src), "uart data null"); UART_CHECK((brk_len > 0 && brk_len < 256), "break_num error"); + //Push data to TX ring buffer and return, ISR will send the data. if(p_uart_obj[uart_num]->tx_buf_size > 0) { if(xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf) > (size)) { uart_event_t evt; - xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mutex, (portTickType)portMAX_DELAY); + xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mux, (portTickType)portMAX_DELAY); evt.type = UART_DATA_BREAK; evt.data.size = size; evt.data.brk_len = brk_len; xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) src, size, portMAX_DELAY); - xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mux); uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); return size; } else { @@ -813,6 +796,7 @@ int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t s return uart_tx_all(uart_num, src, size, 1, brk_len); } } else { + //Send data without TX ring buffer, the task will block until all data have been sent out return uart_tx_all(uart_num, src, size, 1, brk_len); } } @@ -828,29 +812,29 @@ int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait) if(xSemaphoreTake(p_uart_obj[uart_num]->rx_mux,(portTickType)ticks_to_wait) != pdTRUE) { return -1; } - if(p_uart_obj[uart_num]->cur_remain == 0) { + if(p_uart_obj[uart_num]->rx_cur_remain == 0) { ticks_to_wait = ticks_end - xTaskGetTickCount(); data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType) ticks_to_wait); if(data) { - p_uart_obj[uart_num]->head_ptr = data; - p_uart_obj[uart_num]->rd_ptr = data; - p_uart_obj[uart_num]->cur_remain = size; + p_uart_obj[uart_num]->rx_head_ptr = data; + p_uart_obj[uart_num]->rx_ptr = data; + p_uart_obj[uart_num]->rx_cur_remain = size; } else { xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); return -1; } } - val = *(p_uart_obj[uart_num]->rd_ptr); - p_uart_obj[uart_num]->rd_ptr++; - p_uart_obj[uart_num]->cur_remain--; - if(p_uart_obj[uart_num]->cur_remain == 0) { - vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->head_ptr); - p_uart_obj[uart_num]->head_ptr = NULL; - p_uart_obj[uart_num]->rd_ptr = NULL; - if(p_uart_obj[uart_num]->buffer_full_flg) { - BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->data_buf, p_uart_obj[uart_num]->data_len, 1); + val = *(p_uart_obj[uart_num]->rx_ptr); + p_uart_obj[uart_num]->rx_ptr++; + p_uart_obj[uart_num]->rx_cur_remain--; + if(p_uart_obj[uart_num]->rx_cur_remain == 0) { + vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr); + p_uart_obj[uart_num]->rx_head_ptr = NULL; + p_uart_obj[uart_num]->rx_ptr = NULL; + if(p_uart_obj[uart_num]->rx_buffer_full_flg) { + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1); if(res == pdTRUE) { - p_uart_obj[uart_num]->buffer_full_flg = false; + p_uart_obj[uart_num]->rx_buffer_full_flg = false; uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); } } @@ -872,46 +856,40 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp return -1; } while(length) { - if(p_uart_obj[uart_num]->cur_remain == 0) { + if(p_uart_obj[uart_num]->rx_cur_remain == 0) { data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType) ticks_to_wait); if(data) { - p_uart_obj[uart_num]->head_ptr = data; - p_uart_obj[uart_num]->rd_ptr = data; - p_uart_obj[uart_num]->cur_remain = size; -// ets_printf("dbg0\n"); + p_uart_obj[uart_num]->rx_head_ptr = data; + p_uart_obj[uart_num]->rx_ptr = data; + p_uart_obj[uart_num]->rx_cur_remain = size; } else { xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); -// ets_printf("dbg1\n"); return copy_len; } } - if(p_uart_obj[uart_num]->cur_remain > length) { + if(p_uart_obj[uart_num]->rx_cur_remain > length) { len_tmp = length; } else { - len_tmp = p_uart_obj[uart_num]->cur_remain; + len_tmp = p_uart_obj[uart_num]->rx_cur_remain; } -// ets_printf("dbga\n"); - memcpy(buf + copy_len, p_uart_obj[uart_num]->rd_ptr, len_tmp); - p_uart_obj[uart_num]->rd_ptr += len_tmp; - p_uart_obj[uart_num]->cur_remain -= len_tmp; + memcpy(buf + copy_len, p_uart_obj[uart_num]->rx_ptr, len_tmp); + p_uart_obj[uart_num]->rx_ptr += len_tmp; + p_uart_obj[uart_num]->rx_cur_remain -= len_tmp; copy_len += len_tmp; length -= len_tmp; -// ets_printf("dbgb\n"); - if(p_uart_obj[uart_num]->cur_remain == 0) { - vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->head_ptr); - p_uart_obj[uart_num]->head_ptr = NULL; - p_uart_obj[uart_num]->rd_ptr = NULL; - if(p_uart_obj[uart_num]->buffer_full_flg) { - BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->data_buf, p_uart_obj[uart_num]->data_len, 1); -// ets_printf("dbg2\n"); + if(p_uart_obj[uart_num]->rx_cur_remain == 0) { + vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr); + p_uart_obj[uart_num]->rx_head_ptr = NULL; + p_uart_obj[uart_num]->rx_ptr = NULL; + if(p_uart_obj[uart_num]->rx_buffer_full_flg) { + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1); if(res == pdTRUE) { - p_uart_obj[uart_num]->buffer_full_flg = false; + p_uart_obj[uart_num]->rx_buffer_full_flg = false; uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); } } } } -// ets_printf("dbg3\n"); xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); return copy_len; } @@ -926,11 +904,11 @@ esp_err_t uart_flush(uart_port_t uart_num) //rx sem protect the ring buffer read related functions xSemaphoreTake(p_uart->rx_mux, (portTickType)portMAX_DELAY); while(true) { - if(p_uart->head_ptr) { - vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->head_ptr); - p_uart->rd_ptr = NULL; - p_uart->cur_remain = 0; - p_uart->head_ptr = NULL; + if(p_uart->rx_head_ptr) { + vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->rx_head_ptr); + p_uart->rx_ptr = NULL; + p_uart->rx_cur_remain = 0; + p_uart->rx_head_ptr = NULL; } data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType) 0); if(data == NULL) { @@ -938,19 +916,24 @@ esp_err_t uart_flush(uart_port_t uart_num) } vRingbufferReturnItem(p_uart->rx_ring_buf, data); } - p_uart->rd_ptr = NULL; - p_uart->cur_remain = 0; - p_uart->head_ptr = NULL; + p_uart->rx_ptr = NULL; + p_uart->rx_cur_remain = 0; + p_uart->rx_head_ptr = NULL; xSemaphoreGive(p_uart->rx_mux); - xSemaphoreTake(p_uart->tx_mutex, (portTickType)portMAX_DELAY); - do { - data = (uint8_t*) xRingbufferReceive(p_uart->tx_ring_buf, &size, (portTickType) 0); - if(data == NULL) { - break; - } - vRingbufferReturnItem(p_uart->rx_ring_buf, data); - } while(1); - xSemaphoreGive(p_uart->tx_mutex); + + xSemaphoreTake(p_uart->tx_mux, (portTickType)portMAX_DELAY); + if(p_uart->tx_buf_size > 0) { + xSemaphoreTake(p_uart->tx_buffer_mux, (portTickType)portMAX_DELAY); + do { + data = (uint8_t*) xRingbufferReceive(p_uart->tx_ring_buf, &size, (portTickType) 0); + if(data == NULL) { + break; + } + vRingbufferReturnItem(p_uart->rx_ring_buf, data); + } while(1); + xSemaphoreGive(p_uart->tx_buffer_mux); + } + xSemaphoreGive(p_uart->tx_mux); uart_wait_tx_done(uart_num, portMAX_DELAY); uart_reset_fifo(uart_num); return ESP_OK; @@ -1009,7 +992,7 @@ int uart_get_print_port() return s_uart_print_nport; } -esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue, ringbuf_type_t rx_buf_type) +esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); UART_CHECK((rx_buffer_size > 0), "uart rx buffer length error\n"); @@ -1025,11 +1008,16 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary(); p_uart_obj[uart_num]->tx_brk_sem = xSemaphoreCreateBinary(); - p_uart_obj[uart_num]->tx_mutex = xSemaphoreCreateMutex(); - p_uart_obj[uart_num]->tx_buffer_mutex = xSemaphoreCreateMutex(); + p_uart_obj[uart_num]->tx_mux = xSemaphoreCreateMutex(); p_uart_obj[uart_num]->rx_mux = xSemaphoreCreateMutex(); p_uart_obj[uart_num]->intr_num = uart_intr_num; p_uart_obj[uart_num]->queue_size = queue_size; + p_uart_obj[uart_num]->tx_ptr = NULL; + p_uart_obj[uart_num]->tx_head = NULL; + p_uart_obj[uart_num]->tx_len_tot = 0; + p_uart_obj[uart_num]->tx_brk_flg = 0; + p_uart_obj[uart_num]->tx_brk_len = 0; + p_uart_obj[uart_num]->tx_waiting_brk = 0; if(uart_queue) { p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t)); @@ -1038,19 +1026,20 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b } else { p_uart_obj[uart_num]->xQueueUart = NULL; } - p_uart_obj[uart_num]->buffer_full_flg = false; - p_uart_obj[uart_num]->tx_waiting = false; - p_uart_obj[uart_num]->rd_ptr = NULL; - p_uart_obj[uart_num]->cur_remain = 0; - p_uart_obj[uart_num]->head_ptr = NULL; - p_uart_obj[uart_num]->rx_buf_type = rx_buf_type; - p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, rx_buf_type); + p_uart_obj[uart_num]->rx_buffer_full_flg = false; + p_uart_obj[uart_num]->tx_waiting_fifo = false; + p_uart_obj[uart_num]->rx_ptr = NULL; + p_uart_obj[uart_num]->rx_cur_remain = 0; + p_uart_obj[uart_num]->rx_head_ptr = NULL; + p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, RINGBUF_TYPE_BYTEBUF); if(tx_buffer_size > 0) { p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT);//RINGBUF_TYPE_BYTEBUF);//RINGBUF_TYPE_NOSPLIT); p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size; + p_uart_obj[uart_num]->tx_buffer_mux = xSemaphoreCreateMutex(); } else { p_uart_obj[uart_num]->tx_ring_buf = NULL; p_uart_obj[uart_num]->tx_buf_size = 0; + p_uart_obj[uart_num]->tx_buffer_mux = NULL; } } else { ESP_LOGE(UART_TAG, "UART driver already installed\n"); @@ -1097,13 +1086,13 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) vSemaphoreDelete(p_uart_obj[uart_num]->tx_brk_sem); p_uart_obj[uart_num]->tx_brk_sem = NULL; } - if(p_uart_obj[uart_num]->tx_mutex) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_mutex); - p_uart_obj[uart_num]->tx_mutex = NULL; + if(p_uart_obj[uart_num]->tx_mux) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_mux); + p_uart_obj[uart_num]->tx_mux = NULL; } - if(p_uart_obj[uart_num]->tx_buffer_mutex) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_buffer_mutex); - p_uart_obj[uart_num]->tx_buffer_mutex = NULL; + if(p_uart_obj[uart_num]->tx_buffer_mux) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_buffer_mux); + p_uart_obj[uart_num]->tx_buffer_mux = NULL; } if(p_uart_obj[uart_num]->rx_mux) { vSemaphoreDelete(p_uart_obj[uart_num]->rx_mux); diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index 560eb5fdd9..a4205d88dc 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -77,13 +77,9 @@ static int ringbufferFreeMem(ringbuf_t *rb) { int free_size = rb->free_ptr-rb->write_ptr; if (free_size <= 0) free_size += rb->size; - //If we free the last dummy item in the buffer, free_ptr will point to rb->data - //In this case, after we write the last some bytes, the buffer might wrap around if we don't have room for a header anymore. -// if (free_size == 0 && rb->read_ptr == rb->write_ptr) free_size += rb->size; //Reserve one byte. If we do not do this and the entire buffer is filled, we get a situation - //where write_ptr == free_ptr, messing up the next calculation. -// return free_size == 0 ? 0 : free_size - 1; - return free_size - 1; + //where read_ptr == free_ptr, messing up the next calculation. + return free_size-1; } @@ -338,10 +334,6 @@ static uint8_t *getItemFromRingbufByteBuf(ringbuf_t *rb, size_t *length, int wan //can be increase. //This function by itself is not threadsafe, always call from within a muxed section. static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { - ets_printf("in returnItemToRingbufDefault\n"); - xRingbufferPrintInfo(rb); - - uint8_t *data=(uint8_t*)item; configASSERT(((int)rb->free_ptr&3)==0); configASSERT(data >= rb->data); @@ -358,16 +350,9 @@ static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { hdr=(buf_entry_hdr_t *)rb->free_ptr; //basically forward free_ptr until we run into either a block that is still in use or the write pointer. while (((hdr->flags & iflag_free) || (hdr->flags & iflag_dummydata)) && rb->free_ptr != rb->write_ptr) { - if (hdr->flags & iflag_dummydata) { - ets_printf("hrd len: %d; flg: 0x%02x\n",hdr->len,hdr->flags); //Rest is dummy data. Reset to start of ringbuffer. rb->free_ptr=rb->data; - //If the read_ptr is pointing to this dummy item, - //we should also move the read pointer to data, in case we overwrite the read hdr. -// if(rb->read_ptr == (uint8_t*)hdr) { -// rb->read_ptr = rb->data; -// } } else { //Skip past item size_t len=(hdr->len+3)&~3; @@ -378,10 +363,11 @@ static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { if ((rb->data+rb->size)-rb->free_ptr < sizeof(buf_entry_hdr_t)) { rb->free_ptr=rb->data; } + //The free_ptr can not exceed read_ptr, otherwise write_ptr might overwrite read_ptr. + //Read_ptr can not set to rb->data with free_ptr, otherwise write_ptr might wrap around to rb->data. if(rb->free_ptr == rb->read_ptr) break; //Next header hdr=(buf_entry_hdr_t *)rb->free_ptr; - } } @@ -403,12 +389,6 @@ void xRingbufferPrintInfo(RingbufHandle_t ringbuf) configASSERT(rb); ets_printf("Rb size %d free %d rptr %d freeptr %d wptr %d\n", rb->size, ringbufferFreeMem(rb), rb->read_ptr-rb->data, rb->free_ptr-rb->data, rb->write_ptr-rb->data); - buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->read_ptr; - if(rb->write_ptr == rb->read_ptr) { - ets_printf("write que read\n"); - } else { - ets_printf("hdr len: %d; flg: 0x%08x\n", hdr->len, hdr->flags); - } } @@ -516,7 +496,7 @@ BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize, ticks_to_wait = ticks_end - xTaskGetTickCount(); } } while (ringbufferFreeMem(rb) < needed_size && ticks_to_wait>=0); - + //Lock the mux in order to make sure no one else is messing with the ringbuffer and do the copy. portENTER_CRITICAL(&rb->mux); //Another thread may have been able to sneak its write first. Check again now we locked the ringbuff, and retry