forked from espressif/esp-idf
uart: Add missing critical section wrappers around rx_buffered_len
The missing barriers caused uart_get_buffered_data_len() to (very rarely) return a garbage value. When used in MicroPython, though, this caused select() to return and a subsequent read() to stall indefinitely until a char was actually available. Signed-off-by: Chen Yi Qun <chenyiqun@espressif.com> Closes https://github.com/espressif/esp-idf/issues/6397 Merges https://github.com/espressif/esp-idf/pull/6396
This commit is contained in:
committed by
Zim Kalinowski
parent
33a2927dab
commit
abd6ea3087
@@ -176,12 +176,14 @@ esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit)
|
|||||||
esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit)
|
esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit)
|
||||||
{
|
{
|
||||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
||||||
|
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||||
//workaround for hardware bug, when uart stop bit set as 2-bit mode.
|
//workaround for hardware bug, when uart stop bit set as 2-bit mode.
|
||||||
if (UART[uart_num]->rs485_conf.dl1_en == 1 && UART[uart_num]->conf0.stop_bit_num == UART_STOP_BITS_1) {
|
if (UART[uart_num]->rs485_conf.dl1_en == 1 && UART[uart_num]->conf0.stop_bit_num == UART_STOP_BITS_1) {
|
||||||
(*stop_bit) = UART_STOP_BITS_2;
|
(*stop_bit) = UART_STOP_BITS_2;
|
||||||
} else {
|
} else {
|
||||||
(*stop_bit) = UART[uart_num]->conf0.stop_bit_num;
|
(*stop_bit) = UART[uart_num]->conf0.stop_bit_num;
|
||||||
}
|
}
|
||||||
|
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,6 +200,7 @@ esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode)
|
|||||||
esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode)
|
esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode)
|
||||||
{
|
{
|
||||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
||||||
|
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||||
int val = UART[uart_num]->conf0.val;
|
int val = UART[uart_num]->conf0.val;
|
||||||
if(val & UART_PARITY_EN_M) {
|
if(val & UART_PARITY_EN_M) {
|
||||||
if(val & UART_PARITY_M) {
|
if(val & UART_PARITY_M) {
|
||||||
@@ -208,6 +211,7 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode)
|
|||||||
} else {
|
} else {
|
||||||
(*parity_mode) = UART_PARITY_DISABLE;
|
(*parity_mode) = UART_PARITY_DISABLE;
|
||||||
}
|
}
|
||||||
|
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1302,7 +1306,9 @@ esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t* size)
|
|||||||
{
|
{
|
||||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
||||||
UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);
|
UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);
|
||||||
|
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||||
*size = p_uart_obj[uart_num]->rx_buffered_len;
|
*size = p_uart_obj[uart_num]->rx_buffered_len;
|
||||||
|
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1332,14 +1338,19 @@ esp_err_t uart_flush_input(uart_port_t uart_num)
|
|||||||
}
|
}
|
||||||
data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType) 0);
|
data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType) 0);
|
||||||
if(data == NULL) {
|
if(data == NULL) {
|
||||||
|
bool error = false;
|
||||||
|
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||||
if( p_uart_obj[uart_num]->rx_buffered_len != 0 ) {
|
if( p_uart_obj[uart_num]->rx_buffered_len != 0 ) {
|
||||||
ESP_LOGE(UART_TAG, "rx_buffered_len error");
|
|
||||||
p_uart_obj[uart_num]->rx_buffered_len = 0;
|
p_uart_obj[uart_num]->rx_buffered_len = 0;
|
||||||
|
error = true;
|
||||||
}
|
}
|
||||||
//We also need to clear the `rx_buffer_full_flg` here.
|
//We also need to clear the `rx_buffer_full_flg` here.
|
||||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
|
||||||
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
|
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
|
||||||
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||||
|
if (error) {
|
||||||
|
// this must be called outside the critical section
|
||||||
|
ESP_LOGE(UART_TAG, "rx_buffered_len error");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||||
|
Reference in New Issue
Block a user