Skip to content

Race Condition in uarte_nrfx_rx_disable() #92777

@lanwer50

Description

@lanwer50

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

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

Labels

bugThe issue is a bug, or the PR is fixing a bugplatform: nRFNordic nRFxpriority: lowLow impact/importance bug

Type

Projects

Status

To triage

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions