Merge branch 'bugfix/fix_uart_read_bug_when_using_dual_core_v3.2' into 'release/v3.2'
driver(uart): fixed uart read error bug when using dual core (backport v3.2) See merge request idf/esp-idf!3813
This commit is contained in:
commit
4f805d558c
1 changed files with 29 additions and 13 deletions
|
@ -875,6 +875,7 @@ static void uart_rx_intr_handler_default(void *param)
|
|||
//If we fail to push data to ring buffer, we will have to stash the data, and send next time.
|
||||
//Mainly for applications that uses flow control or small ring buffer.
|
||||
if(pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->rx_data_buf, p_uart->rx_stash_len, &HPTaskAwoken)) {
|
||||
p_uart->rx_buffer_full_flg = true;
|
||||
uart_disable_intr_mask(uart_num, UART_RXFIFO_TOUT_INT_ENA_M | UART_RXFIFO_FULL_INT_ENA_M);
|
||||
if (uart_event.type == UART_PATTERN_DET) {
|
||||
if (rx_fifo_len < pat_num) {
|
||||
|
@ -893,7 +894,6 @@ static void uart_rx_intr_handler_default(void *param)
|
|||
}
|
||||
}
|
||||
uart_event.type = UART_BUFFER_FULL;
|
||||
p_uart->rx_buffer_full_flg = true;
|
||||
} else {
|
||||
UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
|
||||
if (uart_intr_status & UART_AT_CMD_CHAR_DET_INT_ST_M) {
|
||||
|
@ -1164,6 +1164,22 @@ int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t si
|
|||
return uart_tx_all(uart_num, src, size, 1, brk_len);
|
||||
}
|
||||
|
||||
static bool uart_check_buf_full(uart_port_t uart_num)
|
||||
{
|
||||
if(p_uart_obj[uart_num]->rx_buffer_full_flg) {
|
||||
BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1);
|
||||
if(res == pdTRUE) {
|
||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||
p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len;
|
||||
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
|
||||
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||
uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait)
|
||||
{
|
||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1));
|
||||
|
@ -1184,8 +1200,17 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp
|
|||
p_uart_obj[uart_num]->rx_ptr = data;
|
||||
p_uart_obj[uart_num]->rx_cur_remain = size;
|
||||
} else {
|
||||
xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);
|
||||
return copy_len;
|
||||
//When using dual cores, `rx_buffer_full_flg` may read and write on different cores at same time,
|
||||
//which may lose synchronization. So we also need to call `uart_check_buf_full` once when ringbuffer is empty
|
||||
//to solve the possible asynchronous issues.
|
||||
if(uart_check_buf_full(uart_num)) {
|
||||
//This condition will never be true if `uart_read_bytes`
|
||||
//and `uart_rx_intr_handler_default` are scheduled on the same core.
|
||||
continue;
|
||||
} else {
|
||||
xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);
|
||||
return copy_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(p_uart_obj[uart_num]->rx_cur_remain > length) {
|
||||
|
@ -1206,16 +1231,7 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp
|
|||
vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr);
|
||||
p_uart_obj[uart_num]->rx_head_ptr = NULL;
|
||||
p_uart_obj[uart_num]->rx_ptr = NULL;
|
||||
if(p_uart_obj[uart_num]->rx_buffer_full_flg) {
|
||||
BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1);
|
||||
if(res == pdTRUE) {
|
||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||
p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len;
|
||||
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
|
||||
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||
uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num);
|
||||
}
|
||||
}
|
||||
uart_check_buf_full(uart_num);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue