Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nrfx_uart bug

Hi,

nrfx_uart.c has a bug where, once there is a RX error, the receiver gets stuck in a disabled state forever.  This is because p_cb->rx_enabled is never set true, so the error handler in uart_irq_handler disables the RX task.  This fixes it:

@@ -406,60 +408,12 @@ nrfx_err_t nrfx_uart_rx(nrfx_uart_t const * p_instance,
 
     if ((!p_cb->rx_enabled) && (!second_buffer))
     {
-        rx_enable(p_instance);
+        nrfx_uart_rx_enable(p_instance);
     }

  • Hi,

    Your fix looks good. Thanks for this! I'll investigate if there are additional places to check with this issue.

    Additionally you can place this change directly to nrfx repository using pull-request on github: github.com/.../

  • Hi,

    I investigated this issue and the code seems to be correct. Clearing rx_enabed flag is not done when error occurs. There is additional information in nrfx_uart_rx_enable documentation:

    The receiver must be explicitly closed by the user see also nrfx_uart_rx_disable.

    Could You check if executing nrfx_uart_rx_disable after receiving error event and handling it works for you?

  • The problem is not that the rx_enabled flag is cleared -- the problem is that it's never set in the first place.  The existing code is clearly wrong, as "nrfx_uart_rx_enabled" is simply never called at all.

    Jim

  • Hi,

    Just wanted to let you know that we have created an internal issue for this, not sure when there will be a fix. This was also added to our known issue post on devzone.

  • I got an update from my colleague:

    Hi Jim,

    We investigated this problem a little. We need you to provide more information about your issue. However we found lacks in our documentation and it will be definitively fixed.

    First of all nrfx_uart driver can work in two (lets say) modes.

    First mode assumes that You know the number of bytes you want to receive (lets call it non-stream mode). When there is no additional space in buffers (buffers first and second are filled up) or any bug occurs then transmission is finished. You can reach this behavior using this set of functions:

    nrfx_uart_init()

    nrfx_uart_rx()

    To keep transmission you have to provide new buffers using nrfx_uart_rx function.

    Second mode looks like lets say stream mode. Data are continously stored into internal hardware fifo. You decide when to stop receiving data using nrfx_uart_rx_disable function.

    // To init uart

    nrfx_uart_init()

     

    // To start filling up hardware fifo with incomming data.

    // For now, software mechanisms and handlers are disabled.

    // Hardware just collecting data into internal fifo.

    nrfx_uart_rx_enable()

     

    // To provide data and enable software mechanism to catch errors

    // and save received data to buffers.

    // In case of error or no space in buffers receiver is still receiving data.

    // You have to react on it and handle it properly.

    nrfx_uart_rx()

     

    // To disable/stop data receiving you have to call explicitely nrfx_uart_rx_disable

    // function. You can also react on RXTO event or discard data.

    nrfx_uart_rx_disable()

    I assume that you are using first mode. In this mode in case of any problem receiver is stopped and buffer lenghts are zeroed. You have to react on error event and directly call nrfx_uart_rx to restart data reception.

    rx_enabled variable is used to store information if receiver is active and managing by developer/aplication/solution using nrfx_uart_rx_enable/disable or managing by driver internally in nrfx_uart_rx function.

    I hope it helps you with your issue.

Related