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

Serial timeout issues with nrf_serial_read() and nrf_serial_write() with nrf_serial_mode_irq.

Hi all,

I'm facing an issue communicating with a UART-based sensor on the NRF52DK (52832).

I've followed the serial_port example and using various forum topics I've got to the point where I can exchange and read data from the sensor using the serial_port methods in IRQ mode. There are 2 issues that come up:

1. If I put "NULL" for the "timeout in ms" parameter in nrf_serial_read() , it seems that the sensor is not able to respond fast enough for my program to receive the transmission and thus I get the NRF_ERROR_TIMEOUT. When NRF_ERROR_TIMEOUT is returned, I  If I do increase the timeout parameter to, say, 1000 ms, the data transmission happens as expected. The problem then, however, is that eventually this might lead to a deadlock. What is the work around to this?

2. How can I decide the size of the read data, if I don't know it until I see what the sensor returns? For example, depending whether the sensor received a command successfully it can return an ACK or NACK with an error code and the size of those transmissions is different. If I put in a larger size of the expected transmission than is actually transmitted, I run into the NRF_ERROR_TIMEOUT again. It seems like there is no way to do that without handling this within the RX event handler, is that correct? What is the best way to handle it?

3. This is not an issue, but it might become later. I'm not completely clear on whether the queues get automatically cleared or not after the RX/TX is done. If not, how can I clear them for RX/TX?

Thanks in advance!

  • Hi,

    1. If you put NULL, the timeout will expire immediately, causing the TIMEOUT error that you see. This is expected. How can increasing the timeout parameter lead to a deadlock?

    2. The p_read parameter will indicate the number of received bytes. The NRF_ERROR_TIMEOUT error can be ignored if this is expected in your application. Setting the SERIAL_BUFF_RX_SIZE parameter to 1 will configure the UART(E) peripheral to receive a single byte at a time and place this into the FIFO, making sure you do not miss any data. However, if you have many other high priority tasks that need to be handled in your application, this may block the serial library from updating the buffer pointer fast enough. An alternative can be to use the async libUARTE library, which implements reliable communication over UART.

    3. The serial_rx/serial_tx functions will pull the data out of the queues. You can call the functions nrf_serial_flush()/nrf_serial_rx_drain() to force this.

    Best regards,
    Jørgen

  • Hi Jørgen,

    First of all, I can make this question public, but I actually posted another question which has the same content, essentially, because I only got one notification when I was editing this post yesterday that it is under review and no further indications of what is happening to it, so I thought it got deleted. I think your answers are a bit more direct than the other engineer's answers to the question and I would like to make this answer available to others too. What is the best way of going about that?

    Now, onto the actual questions:

    1. Oh, alright. I thought that in the documentation that is what was stated:

    "Do not use synchronous API (timeout_ms parameter > 0) in IRQ context. It may lead to a deadlock because the timeout interrupt cannot preempt the current IRQ context."

    2. That makes sense. Would I ignore the TIMEOUT error within the weak_error file or when the actual program runs without the debugger it doesn't actually switch to NRF_BREAKPOINT?

    3. That makes sense, thank you.

    Thank you so much!

  • I requested to convert the ticket to public space, you need to accept it before it is converted.

    1. This section refers to calling the APIs from interrupt context of other peripherals, it does not refer to the IRQ mode used in the nrf_serial library. I'm not sure how the library implements support for timeout=0. To me, it looks like this will generate a TIMEOUT error immediately, but I can have overlooked something in the code.

    2. I would recommend that you filter this error before passing the error code to APP_ERROR_CHECK() macro, for instance like this:

    uint32_t read_bytes = 0;
    ret_code_t err_code = nrf_serial_read(&serial_uart, &c, sizeof(c), &read_bytes, 1000);
    
    if(err_code == NRF_ERROR_TIMEOUT)
    {
        if(read_bytes > 0)
        {
            //Process received data
        }
        else
        {
            //Try read again
        }
    }
    else
    {
        APP_ERROR_CHECK(err_code);
    }

Related