diff --git a/components/esp_driver_uart/include/driver/uart.h b/components/esp_driver_uart/include/driver/uart.h index d0a4e59c761b..fa7f18286a62 100644 --- a/components/esp_driver_uart/include/driver/uart.h +++ b/components/esp_driver_uart/include/driver/uart.h @@ -68,6 +68,8 @@ typedef struct { */ typedef enum { UART_DATA, /*!< UART data event*/ + UART_TX_DONE, /*!< UART TX done*/ // Toit extension. + UART_TX_ENTRY_RETIRED, /*!< UART TX entry retired*/ // Toit extension. UART_BREAK, /*!< UART break event*/ UART_BUFFER_FULL, /*!< UART RX buffer full event*/ UART_FIFO_OVF, /*!< UART FIFO overflow event*/ diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index fdfa21db2227..e9220510aaea 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -84,6 +84,7 @@ static const char *UART_TAG = "uart"; | (UART_INTR_RXFIFO_TOUT) \ | (UART_INTR_RXFIFO_OVF) \ | (UART_INTR_BRK_DET) \ + | (UART_INTR_TX_DONE) /* Toit extension. */ \ | (UART_INTR_PARITY_ERR)) \ | (UART_INTR_WAKEUP) #else @@ -91,6 +92,7 @@ static const char *UART_TAG = "uart"; | (UART_INTR_RXFIFO_TOUT) \ | (UART_INTR_RXFIFO_OVF) \ | (UART_INTR_BRK_DET) \ + | (UART_INTR_TX_DONE) /* Toit extension. */ \ | (UART_INTR_PARITY_ERR)) #endif @@ -1040,6 +1042,8 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) if (p_uart->tx_buf_size == 0) { continue; } + // Toit extension. + bool retired = false; bool en_tx_flg = false; uint32_t tx_fifo_rem = uart_hal_get_txfifo_len(&(uart_context[uart_num].hal)); //We need to put a loop here, in case all the buffer items are very short. @@ -1087,6 +1091,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) need_yield |= (HPTaskAwoken == pdTRUE); p_uart->tx_head = NULL; p_uart->tx_ptr = NULL; + retired = true; // Toit extension. //Sending item done, now we need to send break if there is a record. //Set TX break signal after FIFO is empty if (p_uart->trans_total_remaining_len == 0 && p_uart->tx_brk_flg == 1) { @@ -1114,6 +1119,12 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) } } } + { + // Toit extension. + if (retired) { + uart_event.type = UART_TX_ENTRY_RETIRED; + } + } if (en_tx_flg) { uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TXFIFO_EMPTY); UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); @@ -1197,6 +1208,13 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) uart_pattern_enqueue(uart_num, p_uart->rx_buffered_len + pat_idx); } } + { + // Toit extension: + // No need to send a data event if there is already data queued. + if (uart_event.type == UART_DATA && p_uart->rx_buffered_len > 0) { + uart_event.type = UART_EVENT_MAX; // invalidate event + } + } p_uart->rx_buffered_len += p_uart->rx_stash_len; UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); } @@ -1310,6 +1328,17 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken); need_yield |= (HPTaskAwoken == pdTRUE); } + { + // Toit extension. + // Inform the runtime that everything has been transmitted. + if (p_uart->trans_total_remaining_len == 0) { + UBaseType_t items_waiting; + vRingbufferGetInfo(p_uart->tx_ring_buf, NULL, NULL, NULL, NULL, &items_waiting); + if (items_waiting == 0) { + uart_event.type = UART_TX_DONE; + } + } + } } #if SOC_UART_SUPPORT_WAKEUP_INT else if (uart_intr_status & UART_INTR_WAKEUP) {