NCS UART uart_poll_out with nordic,nrf-uart faulty TX, but works nordic,nrf-uarte

Hi folks,

The blocking transmit function uart_poll_out() works as expected with UARTE, but not with UART.

For our project low power is critical. Thats why I need to use UART (~300 uA) instead of UARTE (~1300 uA). Baud is very low, so DMA does not benefit us.

brd_test.overlay file -> uart0 ->  compatible = "nordic,nrf-uart";

Figure. UART - faulty transmission

brd_test.overlay file -> uart0 ->  compatible = "nordic,nrf-uarte";

Figure. UARTE - transmission OK.

I also tried calling uart_irq_tx_ready() inside ISR -without effect.



I took the echo_bot example and modified it. Here are the files that i modified (i removed RX code for cleanness sake):

5852.main.cpp7028.prj.confbrd_test.overlaybrd_test.dtsi

# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(echo_bot_2)

target_sources(app PRIVATE src/main.cpp)

Second issue is that calling uart_irq_tx_enable(uart_dev) ends in signal handler. Please test it by adding uart_irq_tx_enable() inside uart_tx(). I hoped to work around the faulty transmission by using interrupt driven api, but I cant even enable the tx interrupt in the first place.

Third issue is being able to disable receiver (only async api has RX enable/disable). Unfortunately I couldn't get the async api it to receive in a stable manner. Thats another rant.
For interrupt driven driver I managed to get the sleep power consumption down 2.7 uA by calling pm_device_action_run() manually (as seen in the code). Are there any caveats doing it?

  • Hi

    I will reproduce and test this on my end today and/or tomorrow and get back to you by end of tomorrow with what I find. Thank you for your patience!

    Best regards,

    Simon

  • Yes, I can indeed reproduce it on my end, just wanted to let you know. I will still need some time to take a proper look at your project to see what exactly is happening, but it seems like it's always the 8th bit (stop bit) that is warped on the UART, so something is off there. Note that I used a logic analyzer instead of a scope, but it's still easy to see that it is warped and that it only happens when UART is used instead of UARTE.

    I'll give you another update by end of week. Hopefully we'll be able to find something soon.

    Best regards,

    Simon

  • Hi Leevi

    This seems to be an issue with the end of transmissions in the uart_nrfx_uart driver. But there also seems to be an issue with using 2400 as the baud rate. By setting a delay of 1us at the end of uart_nrfx_poll_out() in uart_nrfx_uart.c let me print the test data correctly when using the UART at 115200 baud rate, but not at a 2400 baud rate.

    Still investigating, but a progress report at least.

    UART frame data with a 1us delay between TX events:

    Best regards,

    Simon

    EDIT: Shortly after we realized what the issue was. In the uart_nrfx_poll_out() function the NRFX_WAIT_FOR() check only attempts to check if the UART is ready for ~1ms, so for lower baud rates this is a bug that will propagate on all lower baud rates. I will report this internally and a proper fix will be added in the future. For now I think increasing the second parameter in the NRFX_WAIT_FOR() function from 1000 to 10000 or just a much higher one should do the trick for lower baud rates as well, but this should be a variable depending on the set baud rate I believe.

    UART frame data where the only change made to your sample was setting the NRFX_WAIT_FOR(event_txdrdy_check(), 10000, 1, res); on line 291 in uart_nrfx_uart.c:

    A more "proper" fix would be replacing the NRFX_WAIT_FOR() function with the following:

    uint8_t ms_per_txbyte = DIV_ROUND_UP((NUM_BITS_PER_TRANSACTION * 1000), BAUDRATE) ;
      NRFX_WAIT_FOR(event_txdrdy_check(), ms_per_txbyte * 1000, 1, res);

    Best regards,

    Simon

Related