diff --git a/components/driver/uart.c b/components/driver/uart.c index b9e7c8495..e6f79c769 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -669,9 +669,9 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_ //Hardware issue workaround: when using ref_tick, the rx timeout threshold needs increase to 10 times. //T_ref = T_apb * APB_CLK/(REF_TICK << CLKDIV_FRAG_BIT_WIDTH) if(UART[uart_num]->conf0.tick_ref_always_on == 0) { - UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh * UART_TOUT_REF_FACTOR_DEFAULT) & UART_RX_TOUT_THRHD_V); + UART[uart_num]->conf1.rx_tout_thrhd = (intr_conf->rx_timeout_thresh * UART_TOUT_REF_FACTOR_DEFAULT); } else { - UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V); + UART[uart_num]->conf1.rx_tout_thrhd = intr_conf->rx_timeout_thresh; } UART[uart_num]->conf1.rx_tout_en = 1; } else { @@ -712,14 +712,19 @@ 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; + int rx_fifo_len = 0; uint8_t buf_idx = 0; - uint32_t uart_intr_status = UART[uart_num]->int_st.val; + uint32_t uart_intr_status = 0; uart_event_t uart_event; portBASE_TYPE HPTaskAwoken = 0; static uint8_t pat_flg = 0; - while(uart_intr_status != 0x0) { - buf_idx = 0; + while(1) { + uart_intr_status = uart_reg->int_st.val; + // The `continue statement` may cause the interrupt to loop infinitely + // we exit the interrupt here + if(uart_intr_status == 0) { + break; + } uart_event.type = UART_EVENT_MAX; if(uart_intr_status & UART_TXFIFO_EMPTY_INT_ST_M) { uart_clear_intr_status(uart_num, UART_TXFIFO_EMPTY_INT_CLR_M); @@ -731,15 +736,12 @@ static void uart_rx_intr_handler_default(void *param) if(p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size == 0) { p_uart->tx_waiting_fifo = false; xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, &HPTaskAwoken); - if(HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR() ; - } } else { //We don't use TX ring buffer, because the size is zero. if(p_uart->tx_buf_size == 0) { continue; } - int tx_fifo_rem = UART_FIFO_LEN - UART[uart_num]->status.txfifo_cnt; + int tx_fifo_rem = UART_FIFO_LEN - uart_reg->status.txfifo_cnt; bool en_tx_flg = false; //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. @@ -760,9 +762,6 @@ static void uart_rx_intr_handler_default(void *param) } //We have saved the data description from the 1st item, return buffer. vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); - if(HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR() ; - } }else if(p_uart->tx_ptr == NULL) { //Update the TX item pointer, we will need this to return item to buffer. p_uart->tx_ptr = (uint8_t*) p_uart->tx_head; @@ -787,9 +786,6 @@ static void uart_rx_intr_handler_default(void *param) 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) { - portYIELD_FROM_ISR() ; - } p_uart->tx_head = NULL; p_uart->tx_ptr = NULL; //Sending item done, now we need to send break if there is a record. @@ -832,8 +828,8 @@ static void uart_rx_intr_handler_default(void *param) } 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) { - p_uart->rx_data_buf[buf_idx++] = uart_reg->fifo.rw_byte; + for(buf_idx = 0; buf_idx < rx_fifo_len; buf_idx++) { + p_uart->rx_data_buf[buf_idx] = uart_reg->fifo.rw_byte; } uint8_t pat_chr = uart_reg->at_cmd_char.data; int pat_num = uart_reg->at_cmd_char.char_num; @@ -893,9 +889,6 @@ static void uart_rx_intr_handler_default(void *param) p_uart->rx_buffered_len += p_uart->rx_stash_len; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); } - if(HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR() ; - } } else { 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); @@ -951,9 +944,6 @@ static void uart_rx_intr_handler_default(void *param) p_uart->tx_waiting_brk = 0; } else { xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken); - if(HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR() ; - } } } else if(uart_intr_status & UART_TX_BRK_IDLE_DONE_INT_ST_M) { uart_disable_intr_mask(uart_num, UART_TX_BRK_IDLE_DONE_INT_ENA_M); @@ -965,9 +955,6 @@ static void uart_rx_intr_handler_default(void *param) 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() ; - } } else { uart_reg->int_clr.val = uart_intr_status; /*simply clear all other intr status*/ uart_event.type = UART_EVENT_MAX; @@ -977,11 +964,10 @@ static void uart_rx_intr_handler_default(void *param) if (pdFALSE == xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken)) { ESP_EARLY_LOGV(UART_TAG, "UART event queue full"); } - if(HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR() ; - } } - uart_intr_status = uart_reg->int_st.val; + } + if(HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); } } @@ -998,7 +984,9 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) return ESP_ERR_TIMEOUT; } xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, 0); - if(UART[uart_num]->status.txfifo_cnt == 0) { + typeof(UART0.status) status = UART[uart_num]->status; + //Wait txfifo_cnt = 0, and the transmitter state machine is in idle state. + if(status.txfifo_cnt == 0 && status.st_utx_out == 0) { xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return ESP_OK; } @@ -1423,3 +1411,4 @@ portMUX_TYPE *uart_get_selectlock() { return &uart_selectlock; } +