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

UART receive in background without callback on nRF52 SDK11

Hi, I'm looking for an easy way to use the UART in blocking mode (or something similiar) with a receive buffer that is filled in background:

  • If possible using EasyDMA for better performance and easier software design
  • TX data may either block until all data has been sent or may return immediately and provide an additional function call to check if all data has been sent successfully.
  • RX data shall received in background and stored in a buffer/FIFO. It shall be possible to read data of arbitrary size from the receive buffer without stopping reception.
  • No callbacks or event handlers shall be used (synchroneous control flow in application).

In the past, on the nRF51, we used the app_uart library with FIFO support. Looking at the SDK11 documentation on infocenter.nordicsemi.com, I couldn't find any information about this library (although the directory is still there in the SDK11 archive). Is app_fifo still working on SDK11 on nRF52? Does it take advantage of the EasyDMA feature?

Looking at nrf_drv_uart.h, double buffering is mentioned to provide support for continuous data reception in non-bocking mode. But what does happen if the last received data byte does not fill the buffer to 100%? Will the driver wait for more bytes until the buffer is full, not giving any opportunity to receive data from the partially filled buffer? In other words, is there any possibility to receive "byte streams" of arbitrary length using UART with EasyDMA (something like app_uart with FIFO feature using EasyDMA)?

  • @puz_md Our next product will be based on nRF52 of course ;)

  • @bat13: if you want to receive continuous data, you can use nrf_drv_uart in EasyDMA mode. As far as I understand, you will get callbacks each time a complete buffer has been received (I didn't try it out yet, though).

    If you want to receive continuous data, the current driver should just work fine (use the double buffering by handing over two buffers with nrf_drv_uart_rx(), and one buffer each time you get the data ready event). But if the data stream suddely stops and your buffer does not become full with the last rx byte, you might wait forever for the final data bytes.

  • "But if the data stream suddely stops and your buffer does not become full with the last rx byte" - That's what I meant, "if the flow is interrupted." As I understand it, periodically causing nrf_drv_uart_rx_abort can interrupt the reception NRF_UARTE_EVENT_RXTO. But what next? if automatic switching to the second buffer will happen? And you can analyze the leisurely first buffer? Where can I read more about the behavior nrf52 in this case?

  • @bat13: That's the idea I had myself. It would be nice if after a RX abort, if the second buffer would immediately be activated. Just try it out and give me some feedback if it works ;-) Although I fear there is a small risk that data may be lost while the EasyDMA buffers are updated by the driver (maybe they will have to trigger the STOP task, update the buffer, and trigger the START task again. And data transmitted within this interval gets lost.

    I have another Idea that I would like to try out: I suppose there shuold be a register containing the current offset within the EasyDMA RX buffer. If this register is readable by software, application code can find out how many bytes have already been received in the current buffer. If you use two adjacent buffers, you could treat them as a circular FIFO and update head and tail each time a RX complete event is triggered. But you can also update the tail and read out some bytes from the active buffer before the event is triggered if you can find out the EasyDMA state. Altough you have to make sure that there are no race conditions when updating the tail (different control flows!). In short, that's what I would like to implement, If I can get some time for this.

  • Quickly I looked through the documentation. DMA has an automatic double buffer. But the trouble is that the access to the current counter is available only after the end of the RX. And, as I understand it, nrf_drv_uart_rx_abort give access, but will interrupt the reception. This may result in loss of data at high speeds, when Ble stack can tighten this pause. Hopefully I missed something.

Related