diff --git a/components/esp8266/driver/uart.c b/components/esp8266/driver/uart.c index 63d2a92b..ae067dd0 100644 --- a/components/esp8266/driver/uart.c +++ b/components/esp8266/driver/uart.c @@ -257,7 +257,18 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) uint32_t baudrate; uint32_t byte_delay_us = 0; BaseType_t res; + portTickType ticks_cur; + portTickType ticks_start = xTaskGetTickCount(); portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; + /** + * Considering the overflow of the ticks_end and the ticks_cur (xTaskGetTickCount()), + * the possible tick timestamp is as follows: + * (one start tick timestamp, two end tick timestamps, four current tick timestamps) + * + * ticks: 0 0xFFFFFFFF + * |_______._______._______._______._______._______._______._______| + * cur1 end1 cur2 start cur3 end2 cur4 + */ // Take tx_mux res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait); @@ -273,10 +284,22 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) uart_get_baudrate(uart_num, &baudrate); byte_delay_us = (uint32_t)(10000000 / baudrate); // (1/baudrate)*10*1000_000 us - ticks_to_wait = ticks_end - xTaskGetTickCount(); + ticks_cur = xTaskGetTickCount(); + if (ticks_start <= ticks_cur) { + ticks_to_wait = ticks_to_wait - (ticks_cur - ticks_start); + } else { + ticks_to_wait = ticks_to_wait - (portMAX_DELAY - ticks_start + ticks_cur); + } // wait for tx done sem. if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, ticks_to_wait)) { while (1) { + ticks_cur = xTaskGetTickCount(); + bool end1_timeout = (ticks_end < ticks_start && ticks_cur < ticks_start && ticks_cur > ticks_end); + bool end2_timeout = (ticks_start < ticks_end && (ticks_cur < ticks_start || ticks_end < ticks_cur)); + if (end1_timeout || end2_timeout) { + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_ERR_TIMEOUT; + } if (UART[uart_num]->status.txfifo_cnt == 0) { ets_delay_us(byte_delay_us); // Delay one byte time to guarantee transmission completion break;