nRF5 SDK  v17.0.2
Choose documentation:
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
Libuarte - advanced UARTE driver

Libuarte is a UARTE library that consists of the following layers:

  • nrf_libuarte_drv – a low level UARTE driver, with extended functionality like a continuous counting of received bytes, double buffering, optional events for starting and stopping receiver, and an optional task that can be triggered when the receiver is started and stopped.
  • nrf_libuarte_async – a library suitable for receiving and transmitting asynchronous packets. It manages the receive buffers and implements the receiver inactivity timeout. The library is using nrf_libuarte. It is meant to be used in a typical UART use case, in which the counterparty is asynchronously sending packets of variable length. In such case, user gets an event on packet boundary (that is, on timeout) and whenever the DMA buffer is full.

See Libuarte Example for Libuarte usage.

nrf_libuarte_drv

nrf_libuarte_drv is using EasyDMA double buffering feature and PPI connections to ensure a reliable reception. The continuous reception is established by the STARTRX task, connected to the ENDRX event. Once the STARTRX task is started, the RXSTARTED event is generated.

On the RXSTARTED event:

  • EasyDMA is configured for the transfer and can be configured for the next transfer.
  • Configuration registers are latched.

Additionally, on the RXSTARTED event, nrf_libuarte_drv is calling the user handler with the request for the next buffer. The handler responds with the new buffer. As long as the buffer is provided before the end of the transfer that has just started, no data will be lost.

With this approach, the system latency depends on the size of the buffers used. If buffers are large enough, the system can ensure the complete reception without flow control with a multimillisecond latency. This minimal latency can cover for the SoftDevice or any other higher priority interrupts and flash operations (including flash page erase).

Moreover, a dedicated TIMER peripheral in the counter mode is used to track the number of bytes received.

nrf_libuarte_drv can be configured with hardware events that will start and stop the receiver. This option can be used, for example, to build a low power UART protocol with request and response pins that will enable the receiver only during a transfer. All hardware tasks and events are connected with PPI, which allows autonomous operation that does not depend on the interrupt handling time.

Hardware resources usage

nrf_libuarte_drv is using the following hardware resources:

  • UARTE instance
  • TIMER instance
  • PPI channels:
    • If optional tasks and events are not used, a minimum of 2 PPI channels (3 on devices with a maximum of 255 EasyDMA transfers).
    • If optional tasks and events are used, a maximum of 9 PPI channels and 2 PPI groups.

nrf_libuarte_drv usage

nrf_libuarte_drv is initialized with nrf_libuarte_drv_init.

The configuration includes:

  • UART configuration (pins, baurdate, hardware flow control and parity)
  • interrupt priority
  • hardware events (start RX, end RX)
  • tasks (RX started, RX done)
  • TIMER peripheral used for counting bytes
  • user event handler

Receiver

The receiver is activated using a call to nrf_libuarte_drv_rx_start with the receive buffer and the information if the receiver should be started immediately or via PPI.

Whenever nrf_libuarte_drv sets a EasyDMA receive buffer, a buffer request event (NRF_LIBUARTE_DRV_EVT_RX_BUF_REQ) is generated. In such case, make sure the application responds with nrf_libuarte_drv_rx_buf_rsp and provides the new buffer. The new receive buffer must be provided before the end of the transfer that has just started, otherwise UARTE will start overwriting the active buffer, since the reception restarts autonomously.

On every completion of the EasyDMA transfer, the NRF_LIBUARTE_DRV_EVT_RX_DATA event is generated.

Transmitter

nrf_libuarte_drv allows transmitting packets with length of 65535 bytes maximum.

If the device does not support 16-bit-long EasyDMA transfers, the EasyDMA double buffering feature and the PPI connection between the ENDTX event and the STARTTX task are used to ensure continouos transfer. On transfer completion, the NRF_LIBUARTE_DRV_EVT_TX_DONE event is generated.


nrf_libuarte_async

nrf_libuarte_async library is built on top of the lib_libuarte_drv driver. It implements a receiver inactivity timeout, which results in an event with the amount of data received.

The library has dedicated buffers for reception and handles the buffer request event from the driver (NRF_LIBUARTE_DRV_EVT_RX_BUF_REQ).

Timeout implementation

You can implement the receiver inactivity timeout using one of the following options, depending on the available resources:

  • a dedicated TIMER peripheral
  • a dedicated RTC peripheral
  • an app_timer instance

TIMER/RTC peripheral

The TIMER or RTC peripheral is used along with the PPI connection between the byte boundary event (RXDRDY) and the task CLEAR in the TIMER/RTC peripheral.

TIMER/RTC is configured in such a way as to trigger an interrupt on the compare event. An interrupt is triggered when a task CLEAR is not triggered on time.

The timeout in configurable and the resolution equals the tick length of the peripheral used.

app_timer instance

Alternatively to TIMER/RTC peripheral, an app_timer instance can be used for the timeout implementation. This approach requires generating an app_timer event periodically at the specified time interval.

At the timeout, the app_timer event handler checks if the number of received bytes has changed. Based on this check, the handler reports the packet boundary.

The timeout resolution is lower compared with TIMER/RTC peripheral and equals the shortest app_timer timeout that can be set.

Hardware resources usage

nrf_libuarte_async is using the following hardware resources:

  • nrf_libuarte_drv driver in the most basic configuration:
    • UARTE instance
    • TIMER instance
    • 2 or 3 PPI channels
  • If TIMER or RTC peripheral is used for the receiver inactivity timeout, the following additional resources are used:
    • RTC or TIMER instance
    • 2 PPI channels

nrf_libuarte_async usage

nrf_libuarte_async is initialized with nrf_libuarte_async_init.

The configuration includes:

  • same elements as for the nrf_libuarte_drv configuration (see nrf_libuarte_drv usage)
  • receiver inactivity timeout
  • timeout infrastructure (TIMER, RTC, or app_timer)
  • amount of memory dedicated for the receiver

Receiver

nrf_libuarte_async_enable enables the receiver.

On packet or buffer boundary, an event handler is called with NRF_LIBUARTE_ASYNC_EVT_RX_DATA. The event structure contains a pointer to the data and the amount of data received. When you process the data, it must be returned to the library with a call to nrf_libuarte_async_rx_free.

Transmitter

nrf_libuarte_async_tx is used to start the transfer.

The event handler with the NRF_LIBUARTE_ASYNC_EVT_TX_DONE event is called on the transfer completion.