drivers: serial: uart_nrfx_uarte: Fix dropping flushed data

When rx_flush() was called with NULL buffer it was an indication to
drop data from the FIFO. However, it is still important to get the
correct amount of dropped data because when PPI+TIMER are used to
count bytes those flushed bytes are also counted (because each
byte generates RXDRDY event). If those bytes are not counted then
total amount of reported bytes is not correctly aligned with bytes
counted by TIMER.

Reworking rx_flush() to correctly count number of dropped bytes and
then add this flushed bytes to the total amount of RX bytes
reported to the user in RXTO event handler.

Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruściński 2024-04-24 16:59:23 +02:00 committed by Anas Nashif
commit 345dd11e20

View file

@ -1208,7 +1208,7 @@ static void endrx_isr(const struct device *dev)
*
* @param dev Device.
* @param buf Buffer for flushed data, null indicates that flushed data can be
* dropped.
* dropped but we still want to get amount of data flushed.
* @param len Buffer size, not used if @p buf is null.
*
* @return number of bytes flushed from the fifo.
@ -1224,7 +1224,6 @@ static uint8_t rx_flush(const struct device *dev, uint8_t *buf, uint32_t len)
size_t flush_len = buf ? len : sizeof(tmp_buf);
if (buf) {
memset(buf, dirty, len);
flush_buf = buf;
flush_len = len;
} else {
@ -1232,6 +1231,7 @@ static uint8_t rx_flush(const struct device *dev, uint8_t *buf, uint32_t len)
flush_len = sizeof(tmp_buf);
}
memset(flush_buf, dirty, flush_len);
nrf_uarte_rx_buffer_set(uarte, flush_buf, flush_len);
/* Final part of handling RXTO event is in ENDRX interrupt
* handler. ENDRX is generated as a result of FLUSHRX task.
@ -1243,10 +1243,6 @@ static uint8_t rx_flush(const struct device *dev, uint8_t *buf, uint32_t len)
}
nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDRX);
if (!buf) {
return nrf_uarte_rx_amount_get(uarte);
}
uint32_t rx_amount = nrf_uarte_rx_amount_get(uarte);
if (rx_amount != prev_rx_amount) {
@ -1254,7 +1250,7 @@ static uint8_t rx_flush(const struct device *dev, uint8_t *buf, uint32_t len)
}
for (int i = 0; i < flush_len; i++) {
if (buf[i] != dirty) {
if (flush_buf[i] != dirty) {
return rx_amount;
}
}
@ -1306,8 +1302,16 @@ static void rxto_isr(const struct device *dev)
*/
data->async->rx_enabled = false;
if (data->async->discard_rx_fifo) {
uint8_t flushed;
data->async->discard_rx_fifo = false;
(void)rx_flush(dev, NULL, 0);
flushed = rx_flush(dev, NULL, 0);
if (HW_RX_COUNTING_ENABLED(data)) {
/* It need to be included because TIMER+PPI got RXDRDY events
* and counted those flushed bytes.
*/
data->async->rx_total_user_byte_cnt += flushed;
}
}
if (config->flags & UARTE_CFG_FLAG_LOW_POWER) {