Description
Describe the bug
While updating from zephyr v3.2.0 to the LTS version v3.71, I got aware of the race condition happening when uarte_nrfx_rx_disable
is interrupted by rxto_isr()
in drivers/serial/uart_nrfx_uarte.c
. See further details in #77060.
This was mitigated in v4.0.0-rc1 by adding an irq_lock() to uarte_nrfx_rx_disable
.
Related MR: #80015
Related Commit: 317de0c
However, I noticed that the issue is still present when using high baudrates (460800).
Steps to reproduce
- Develop a uarte application that uses a high baud rate (460800 or above).
- Continuously start and stop reading data from the UART
Impact
RX can no longer be activated.
Major – Severely degrades functionality; workaround is difficult or unavailable.
Environment
- OS: Linux
- Zephyr v3.7.1 with added fix from drivers: serial: nrfx_uarte: Add support to DMM and data cache and other minor tweaks #80015
Proposed Solution
The lock should be acquired in the very beginning of uarte_nrfx_rx_disable
to protect e.g. the rx_buf from being manipulated in the rxto_isr()
while being checked in uarte_nrfx_rx_disable
.
This is the suggested version:
static int uarte_nrfx_rx_disable(const struct device *dev)
{
int key = irq_lock();
struct uarte_nrfx_data *data = dev->data;
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
if (data->async->rx_buf == NULL) {
irq_unlock(key);
return -EFAULT;
}
k_timer_stop(&data->async->rx_timeout_timer);
if (data->async->rx_next_buf != NULL) {
nrf_uarte_shorts_disable(uarte, NRF_UARTE_SHORT_ENDRX_STARTRX);
nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED);
}
data->async->rx_enabled = false;
data->async->discard_rx_fifo = true;
nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPRX);
irq_unlock(key);
return 0;
}
Metadata
Metadata
Assignees
Type
Projects
Status