Asynchronous UART API (DMA) not working like expected on nrf52840

hi,
i am trying to use the async uart api on a nrf52840 for communicating to a quectel bg95 modem.
no matter which timeout or buffer-size i am using, i am experiencing the problem that that some (1-2) bytes of the modem response are not received (or forwarded via the api) when they are arriving ... they are received with delay, when the next response of the modem comes in.

so the usual communication flow to the modem is:
(1) request from nrf -> modem
(2) response from the modem -> nrf (usually ending with "\r\n")
(3) some delay
(4) next request from nrf -> modem
(5) next response from the modem -> nrf

when using the async api it happens very often, that one or both of "\r\n" of (2) are missing as long as the response of (5) is beginning to come in. then the response of (5) is prepended with the missing "\r\n" of (2).

  • The async uart dma driver counts the RXRDY events which are raised by the nrf-hardware immediately after detecting a fully received byte, but potentially before transferring it to the dma memory buffer (see nrf52840 datasheet). This counting is done within an ISR. And this counted value is used by the driver logic when executing the timer-timeout event.

    There is some comment within the driver source code (around line 1075 in uart_nrfx_uarte.c) that it might happen that this counting is wrong due to latencies in handling interrupts.

    With the debugger I can confirm, that the driver falls into this "if (len<0) {...}", where wrong counts are handled, in the case that the problem occurs.

    It does not fall into this branch, when CONFIG_NETWORKING is disabled.This is the case where everything works fine.

    So for me it seems that CONFIG_NETWORKING does some ISR handling which takes too long time, blocking the RXRDY isr handling for too long time, which leads to wrong byte counting.

    CONFIG_NETWORKING adds quite a big amount of source code to the project, therefore I am kind of lost where to look for the long-lasting isr handling.

    So I would really appreciate any hint for how to get out of this problem!

  • Finally I managed to find the solution by myself:

    add the following lines to prj.conf:

    CONFIG_UART_0_ASYNC=y
    CONFIG_UART_0_NRF_HW_ASYNC=y
    CONFIG_UART_0_NRF_HW_ASYNC_TIMER=0

    some kind of documentation about this would have helped me a lot.
    menuconfig did not help either, because when setting the timer instance number there, compilation fails afterwards.

Related