From 13303c4351d9b88f0c522cf5b5a4835a42cb6403 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Thu, 4 Jun 2020 16:12:06 +0200 Subject: [PATCH] drivers: serial: nrf uarte: Fix for the RX byte counter In case of the following sequence of UART events: - UART_ENDRX - UART_RXRDY - TIMER_RXTIMEOUT The application receives one more byte that was received, due to RX counter alignment upon ENDRX event. The proposed fix moves the RX byte counter alignment to the RX timeout event handler. Signed-off-by: Tomasz Chyrowicz --- drivers/serial/uart_nrfx_uarte.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index 8b7442dfa68f9a..0704a3f45e8575 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -935,6 +935,17 @@ static void rx_timeout(struct k_timer *timer) int32_t len = data->async->rx_total_byte_cnt - data->async->rx_total_user_byte_cnt; + if (!hw_rx_counting_enabled(data) && + (len < 0)) { + /* Prevent too low value of rx_cnt.cnt which may occur due to + * latencies in handling of the RXRDY interrupt. + * At this point, the number of received bytes is at least + * equal to what was reported to the user. + */ + data->async->rx_cnt.cnt = data->async->rx_total_user_byte_cnt; + len = 0; + } + /* Check for current buffer being full. * if the UART receives characters before the the ENDRX is handled * and the 'next' buffer is set up, then the SHORT between ENDRX and @@ -1043,15 +1054,6 @@ static void endrx_isr(const struct device *dev) data->async->rx_total_user_byte_cnt += rx_len; - if (!hw_rx_counting_enabled(data)) { - /* Prevent too low value of rx_cnt.cnt which may occur due to - * latencies in handling of the RXRDY interrupt. Because whole - * buffer was filled we can be sure that rx_total_user_byte_cnt - * is current total number of received bytes. - */ - data->async->rx_cnt.cnt = data->async->rx_total_user_byte_cnt; - } - /* Only send the RX_RDY event if there is something to send */ if (rx_len > 0) { notify_uart_rx_rdy(dev, rx_len);