mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-05-17 23:27:06 +08:00
fix: potential blocking code when call uart_wait_tx_done()
1. there is a risk of ticks_end overflow, if xTaskGetTickCount() plus ticks_to_wait is bigger than portMAX_DELAY 2. potential blocking code on waiting for tx fifo done. It usually occurs at esp uart uses flow control, and the other side of uart not.
This commit is contained in:
@ -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;
|
||||
|
Reference in New Issue
Block a user