Merge branch 'bugfix/uart_tx_done_timeout_check' into 'master'

fix(uart): potential blocking code when call uart_wait_tx_done()

See merge request sdk/ESP8266_RTOS_SDK!1599
This commit is contained in:
Dong Heng
2021-04-28 11:39:26 +00:00

View File

@ -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;