Hi Nordic team,
I have a curious problem I need a little help with:
(NRF52840 & SDK 15.3)
I have a project which is an integration of the ble_uart example and the serial_uartes example. I've removed all references to the older app_uart functions in the ble code and instead use the newer nrf_serial library to configure both UARTEs as follows:
UARTE0: DMA, priority 6, flow control disabled, 9600 baud, RX on P0.13, TX on P0.15 (connected to a GPS device)
UARTE1: DMA, priority 6, flow control disabled, 115200 baud, RX on P0.29, TX on P0.31 (connected to a PC)
NRF_LOGGING is disabled so that I can send my own debug to UARTE1.
After programming or soft-reset, everything works fine - the GPS device gets configured correctly by commands sent to it on UARTE0, and data is received and decoded properly from it. Debug messages are sent to UARTE1 correctly, and I can also send debug strings from my PC via UARTE1 and have them sent over ble to my phone. All hunky dory.
The problem arises when I power-cycle the board: UARTE0 stops receiving characters from the GPS, i.e. the RX_DATA event never fires. I know that the GPS is sending them, and I know that it has been configured correctly, so UARTE0 Tx seems fine. UARTE1 also works fine in both directions. It is just UARTE0 RX that fails. I have tried swapping over the instances of the 2 UARTEs but it makes no difference. The only thing I can't change is the pin config: GPS data comes in on P0.13. If I disable the ble code, so that the project behaves more or less like the serial_uartes example, then the problem seems to go away, and I can power cycle the board without problems. So it seems to be something to do with initialising the ble stack, I think.
Likely you may avoid your problem if you use an external pull-up resistor on the RXD line, since the problem here is likely caused by floating input pin which will stop, assert or hardfault the application.
However the serial library is not great at handling errors in general, so my recommendation is to not use the serial library, but instead use nrf_drv_uart.h directly, by using the functions nrf_drv_uart_rx(...) and nrf_drv_uart_tx(...). For instance the nrf_cli and our serializers use nrf_drv_uart.h directly. By using the driver directly you also have full control of how you want to handle UART errors (e.g. ignore them instead of hard faulting/stopping UART to work).
Alternatively I would recommend to try nrf_libuarte_async driver for UARTE and lossless reception without HWFC. There are experimental_cli_libuarte and experimental_libuarte example in the SDK that show usage. They are labelled experimental due to lack of documentation but it has been thoroughly tested. The stability and quality of the libuarte is very good. The libuarte library requires one TIMER, one RTC or TIMER, couple of PPI channels (~3 if recall correctly).
I think I know what is causing the overrun error on power up - the GPS engine defaults to sending half a dozen NMEA messages every second before I reconfigure it for one message every 5 seconds. When I do a soft reset the GPS is already reconfigured so I don't get the overruns.
I figured the solution would be to do call nrf_serial_rx_drain(xxxx) when the NRF_SERIAL_EVENT_DRV_ERR event occurs, but this is making no difference, and I continue to get an overrun error even when the GPS been has slowed down, unless I soft-reset.