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?

Parents
  • 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

Reply
  • 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

Children
No Data
Related