Skip to content

Commit 65a9969

Browse files
ananglrlubos
authored andcommitted
[nrf fromtree] drivers: uart_nrfx_uarte: Prevent re-enabling RX until...
UART_RX_DISABLED Fix the driver so that after a call to uart_rx_disable() it does not allow re-enabling RX until the UART_RX_DISABLED is generated (what means that the disabling procedure is complete). Otherwise, it is possible that the RXTO event from the previous RX is handled right after a new RX is started, and the RX buffer pointer gets corrupted in the `rx_flush()` function. Signed-off-by: Andrzej Głąbek <[email protected]> (cherry picked from commit c984a34) Signed-off-by: Pavel Vasilyev <[email protected]>
1 parent 93b389f commit 65a9969

File tree

1 file changed

+18
-11
lines changed

1 file changed

+18
-11
lines changed

drivers/serial/uart_nrfx_uarte.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ struct uarte_async_cb {
112112
atomic_t low_power_mask;
113113
uint8_t rx_flush_buffer[UARTE_HW_RX_FIFO_SIZE];
114114
uint8_t rx_flush_cnt;
115-
bool rx_enabled;
115+
volatile bool rx_enabled;
116+
volatile bool discard_rx_fifo;
116117
bool hw_rx_counting;
117118
bool pending_tx;
118119
/* Flag to ensure that RX timeout won't be executed during ENDRX ISR */
@@ -897,7 +898,11 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf,
897898
return -ENOTSUP;
898899
}
899900

900-
if (data->async->rx_enabled) {
901+
/* Signal error if RX is already enabled or if the driver is waiting
902+
* for the RXTO event after a call to uart_rx_disable() to discard
903+
* data from the UARTE internal RX FIFO.
904+
*/
905+
if (data->async->rx_enabled || data->async->discard_rx_fifo) {
901906
return -EBUSY;
902907
}
903908

@@ -1013,6 +1018,7 @@ static int uarte_nrfx_rx_disable(const struct device *dev)
10131018

10141019
k_timer_stop(&data->async->rx_timeout_timer);
10151020
data->async->rx_enabled = false;
1021+
data->async->discard_rx_fifo = true;
10161022

10171023
nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPRX);
10181024

@@ -1334,16 +1340,17 @@ static void rxto_isr(const struct device *dev)
13341340
rx_buf_release(dev, &data->async->rx_buf);
13351341
rx_buf_release(dev, &data->async->rx_next_buf);
13361342

1337-
/* If the rx_enabled flag is still set at this point, it means that
1338-
* RX is being disabled because all provided RX buffers have been
1339-
* filled up. Clear the flag then, so that RX can be enabled again.
1340-
*
1341-
* If the flag is already cleared, it means that RX was aborted by
1342-
* a call to uart_rx_disable() and data from FIFO should be discarded.
1343+
/* This point can be reached in two cases:
1344+
* 1. RX is disabled because all provided RX buffers have been filled.
1345+
* 2. RX was explicitly disabled by a call to uart_rx_disable().
1346+
* In both cases, the rx_enabled flag is cleared, so that RX can be
1347+
* enabled again.
1348+
* In the second case, additionally, data from the UARTE internal RX
1349+
* FIFO need to be discarded.
13431350
*/
1344-
if (data->async->rx_enabled) {
1345-
data->async->rx_enabled = false;
1346-
} else {
1351+
data->async->rx_enabled = false;
1352+
if (data->async->discard_rx_fifo) {
1353+
data->async->discard_rx_fifo = false;
13471354
(void)rx_flush(dev, NULL, 0);
13481355
}
13491356

0 commit comments

Comments
 (0)