This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Buffering UART data

I know this has been asked a couple of times, but I haven't been able to find a straight forward answer.

I have a GPS module that spits out data via UART (no flow control). I would like to have the data stored into a buffer until I am ready to ready read it. The buffer might still be empty, partially filled, or full when I read it. Doesn't matter, I just want to read whatever is there whenever I want. If the buffer gets filled, it's fine if the data gets dropped. I plan to make the buffer big enough that that shouldn't happen, but if it does, doesn't matter.

If it makes a difference, I am running the nRF52840 in a mesh network (Mesh SDK 4.1.0 / SDK 16.0.0). Working off the light switch example.

I've read about using app_uart.c, app_uart_fifo.c, the serial library, etc and am just not sure what to use to accomplish this.

Then there is UART vs UARTE. If I understand what I read correctly, UARTE with EasyDMA can directly put the data in a buffer, but I can't go read it until the buffer is full and not before?

Thanks.

  • That did not work. I don't think it's that simple. nrfx_uarte_rx() says that the receive buffer is double-buffered so that it can receive data continuously.

    The data I want to receive comes in different lengths. Lets say 15, 17, and then 21 bytes. And I know that it will never be longer than 21 bytes. So I set the receiver buffer size to 21 bytes. The way I understand it:

    1. I call nrfx_uarte_init(), then nrfx_uarte_rx(), and it waits to receive data.

    2. Receives 15 bytes and puts it into buffer.

    3. Receives 17 bytes and generates NRFX_UARTE_EVT_RX_DONE event. I process the data and call nrfx_uarte_rx() to receive more. But at this point 11 bytes of the 17 bytes has overflowed and is already occupying the 'second' buffer.

    4. Receives 21 bytes into 'second' buffer and puts the data after the 11 bytes that are already there. Generates NRFX_UARTE_EVT_RX_DONE event.

    What I want is to start nrfx_uarte_rx() 'fresh' every time. I understand that the 17 byte packet could be lost if it gets sent before I call nrfx_uarte_rx() again. Basically I don't need the double-buffering.

    Edit: I did try the following when receiving the NRFX_UARTE_EVT_RX_DONE event:

    nrfx_uarte_uninit(&m_uarte)
    memset(uart_rx_buffer, 0, sizeof(uart_rx_buffer))
    nrfx_uarte_init(&m_uarte, &config, uart_event_handler)
    nrfx_uarte_rx(&m_uarte, uart_rx_buffer, sizeof(uart_rx_buffer))

    But after I did that, I stopped receiving NRFX_UARTE_EVT_RX_DONE events all together.

    Thanks.

  • Hi,

    There are some misunderstandings here.

    ftjandra said:
    nrfx_uarte_rx() says that the receive buffer is double-buffered so that it can receive data continuously.

    I am not sure we are talking about the same thing. The UARTE peripheral does not have a double buffered receive buffer in the same way as the UART, as it just copies data into RAM. The RXD.PTR register is double-buffered though, but this just holds the address of the receive buffer in RAM.

    ftjandra said:
    3. Receives 17 bytes and generates NRFX_UARTE_EVT_RX_DONE event. I process the data and call nrfx_uarte_rx() to receive more. But at this point 11 bytes of the 17 bytes has overflowed and is already occupying the 'second' buffer.

    If that is the case, then you should perhaps use longer buffers, switch buffers immediately (this is why the PTR registers are double-buffered), or use flow control (which is usually a good idea anyway).

  • I ended up making my parser smarter so that it doesn't care if the data starts at the beginning or not. So this doesn't matter anymore. Thanks for all the help!

Related