| nRF5 SDK v12.0.0 |

Choose documentation: | nRF5 SDK | S130 SoftDevice API | S132 SoftDevice API | S212 SoftDevice API | S332 SoftDevice API

All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
UART

The UART driver includes two layers: the hardware access layer (HAL) and the driver layer (DRV).

The hardware access layer provides basic APIs for accessing the registers of the UART and UARTE peripherals. See the API documentation for the UART HAL and UARTE HAL for details.

The driver layer provides APIs on a higher level than the HAL. See the API documentation for the UART driver for details.

Key features include:

- Multi-instance support.
- Common API for two types of peripherals: legacy peripherals (UART) and peripherals using EasyDMA (UARTE). The type of peripheral that is used can be configured either during build time or at runtime during initialization.
- Two modes of data transfer: blocking and non-blocking (with end notification done via an event handler that is provided during initialization).
- Driver supports aborting ongoing RX or TX transfers.
- Supported modes: with and without hardware flow control and with and without parity bit.
- Double RX buffering allowing to receive data continuously.

Note that peripherals using EasyDMA can work only with buffers that are placed in the Data RAM region. Under certain circumstances, compilers might choose to use a different region for data placement and, for example, place a constant buffer in the code FLASH. In such a case, the UARTE peripheral cannot be used to transfer data from the buffer.

# Driver configuration

The UART driver can use multiple instances of the UART/UARTE peripherals, and it provides a common API for both peripheral types. The instances of the peripherals that are to be assigned to the driver must be selected statically in `sdk_config.h`. In the same way, you configure whether a given instance uses EasyDMA.

The UART default configuration is located in `sdk_config.h`. If UARTE is present on the chip, the driver can be configured at runtime to support UART mode, UARTE mode, or both. The following example shows how to configure the driver to support both modes in runtime and have legacy mode as the default:

#ifdef NRF52
#define UART0_USE_EASY_DMA false
#define UART_EASY_DMA_SUPPORT 1
#define UART_LEGACY_SUPPORT 1
#endif //NRF52

If only one mode is used in the application, disable the second mode in `sdk_config.h` to achieve a lower memory footprint and better performance.

Call nrf_drv_uart_init with the p_config argument set to NULL to use the default configuration. To use a custom configuration, provide a user configuration structure, for example:

nrf_drv_uart_t uart_driver_instance = NRF_DRV_UART_INSTANCE(UART0_INSTANCE_INDEX);
nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG;
config.use_easy_dma = true;
ret_code = nrf_drv_uart_init(&uart_driver_instance, &config, NULL);

# Using the UART driver

## Blocking mode

If no event handler is provided during the initialization of the driver, the driver will operate in blocking mode. In this case, nrf_drv_uart_tx and nrf_drv_uart_rx will not return until the requested transfer is completed, nrf_drv_uart_rx_abort or nrf_drv_uart_tx_abort is called from a different context, or an error is detected. When an abort function is called, nrf_drv_uart_tx or nrf_drv_uart_rx returns with an error code. When an error is reported by the peripheral,nrf_drv_uart_rx returns with an error code.

In blocking mode, the driver does not use a peripheral interrupt, and there is no context switching inside the driver.

## Non-blocking mode

If an event handler (nrf_uart_event_handler_t) is provided during the initialization of the driver, the driver will operate in non-blocking mode. In this case, nrf_drv_uart_tx and nrf_drv_uart_rx will return immediately after transfer is started. Completion will be notified to the user by the event handler that was provided during initialization. The event handler is called in the context of the UART/UARTE interrupt. If an error is reported by the peripheral, it is also reported by the event handler. The error event contains information about the amount of data that was transferred before the error occurred.

If nrf_drv_uart_rx_abort or nrf_drv_uart_tx_abort is called, the event handler notifies that the transfer is completed, but the length field is set to the amount of data that was transferred before the abort function was called.

## Enabling RX without providing data buffer

You can enable RX without providing a buffer for incoming data. In this case, incoming data (up to 6 bytes) stays in the hardware FIFO. If more than 6 bytes are received, an overrun error condition occurs. This condition will be reported by the event handler or at the next nrf_drv_uart_rx call.

Note
  This functionality is provided only for UART mode.

nrf_drv_uart_t uart_driver_instance = NRF_DRV_UART_INSTANCE(UART0_INSTANCE_INDEX);
ret_code = nrf_drv_uart_init(&uart_driver_instance, NULL, NULL);
nrf_drv_uart_rx_enable(&uart_driver_instance);
//UART RX is enabled
nrf_drv_uart_rx(&uart_driver_instance, buffer, 2);
//UART RX is still enabled.
nrf_drv_uart_rx_disable(&uart_driver_instance);