UART

Overview

A Universal Asynchronous Receiver/Transmitter (UART) is a component known to handle the timing requirements for a variety of widely-adapted interfaces (RS232, RS485, RS422, …). A UART provides a widely adopted and cheap method to realize full-duplex or half-duplex data exchange among different devices.

There are three UART controllers available on the ESP32 chip. They are compatible with UART-enabled devices from various manufacturers. All UART controllers integrated in the ESP32 feature an identical set of registers for ease of programming and flexibility. In this documentation, these controllers are referred to as UART0, UART1, and UART2.

Functional Overview

The following overview describes functions and data types used to establish communication between ESP32 and some other UART device. The overview reflects a typical workflow when programming ESP32’s UART driver and is broken down into the following sections:

  1. Setting Communication Parameters - baud rate, data bits, stop bits, etc,
  2. Setting Communication Pins - pins the other UART is connected to
  3. Driver Installation - allocate ESP32’s resources for the UART driver
  4. Running UART Communication - send / receive the data
  5. Using Interrupts - trigger interrupts on specific communication events
  6. Deleting Driver - release ESP32’s resources, if UART communication is not required anymore

The minimum to make the UART working is to complete the first four steps, the last two steps are optional.

The driver is identified by uart_port_t, that corresponds to one of the tree UART controllers. Such identification is present in all the following function calls.

Setting Communication Parameters

There are two ways to set the communications parameters for UART. One is to do it in one shot by calling uart_param_config() provided with configuration parameters in uart_config_t structure.

The alternate way is to configure specific parameters individually by calling dedicated functions:

Configuration example:

const int uart_num = UART_NUM_2;
uart_config_t uart_config = {
    .baud_rate = 115200,
    .data_bits = UART_DATA_8_BITS,
    .parity = UART_PARITY_DISABLE,
    .stop_bits = UART_STOP_BITS_1,
    .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
    .rx_flow_ctrl_thresh = 122,
};
// Configure UART parameters
ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));

All the above functions have a _get_ equivalent to retrieve the current setting, e.g. uart_get_baudrate().

Setting Communication Pins

In next step, after configuring communication parameters, we are setting physical GPIO pin numbers the other UART will be connected to. This is done in a single step by calling function uart_set_pin() and providing it with GPIO numbers, that driver should use for the Tx, Rx, RTS and CTS signals.

Instead of GPIO pin number we can enter a macro UART_PIN_NO_CHANGE and the currently allocated pin will not be changed. The same macro should be entered if certain pin will not be used.

// Set UART pins(TX: IO16 (UART2 default), RX: IO17 (UART2 default), RTS: IO18, CTS: IO19)
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, 18, 19));

Driver Installation

Once configuration of driver is complete, we can install it by calling uart_driver_install(). As result several resources required by the UART will be allocated. The type / size of resources are specified as function call parameters and concern:

  • size of the send buffer
  • size of the receive buffer
  • the event queue handle and size
  • flags to allocate an interrupt

Example:

// Setup UART buffered IO with event queue
const int uart_buffer_size = (1024 * 2);
QueueHandle_t uart_queue;
// Install UART driver using an event queue here
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, uart_buffer_size, \
                                        uart_buffer_size, 10, &uart_queue, 0));

If all above steps have been complete, we are ready to connect the other UART device and check the communication.

Running UART Communication

The processes of serial communication are under control of UART’s hardware FSM. The data to be sent should be put into Tx FIFO buffer, FSM will serialize them and sent out. A similar process, but in reverse order, is done to receive the data. Incoming serial stream is processed by FSM and moved to the Rx FIFO buffer. Therefore the task of API’s communication functions is limited to writing and reading the data to / from the respective buffer. This is reflected in some function names, e.g.: uart_write_bytes() to transmit the data out, or uart_read_bytes() to read the incoming data.

Transmitting

The basic API function to write the data to Tx FIFO buffer is uart_tx_chars(). If the buffer contains not sent characters, this function will write what fits into the empty space and exit reporting the number of bytes actually written.

There is a ‘companion’ function uart_wait_tx_done() that waits until all the data are transmitted out and the Tx FIFO is empty.

// Wait for packet to be sent
const int uart_num = UART_NUM_2;
ESP_ERROR_CHECK(uart_wait_tx_done(uart_num, 100)); // wait timeout is 100 RTOS ticks (TickType_t)

An easier to work with function is uart_write_bytes(). It sets up an intermediate ring buffer and exits after copying the data to this buffer. When there is an empty space in the FIFO, the data are moved from the ring buffer to the FIFO in the background by an ISR. The code below demonstrates using of this function.

// Write data to UART.
char* test_str = "This is a test string.\n";
uart_write_bytes(uart_num, (const char*)test_str, strlen(test_str));

There is a similar function as above that adds a serial break signal after sending the data - uart_write_bytes_with_break(). The ‘serial break signal’ means holding TX line low for period longer than one data frame

// Write data to UART, end with a break signal.
uart_write_bytes_with_break(uart_num, "test break\n",strlen("test break\n"), 100);

Receiving

To retrieve the data received by UART and saved in Rx FIFO, use function uart_read_bytes(). You can check in advance what is the number of bytes available in Rx FIFO by calling uart_get_buffered_data_len(). Below is the example of using this function:

// Read data from UART.
const int uart_num = UART_NUM_2;
uint8_t data[128];
int length = 0;
ESP_ERROR_CHECK(uart_get_buffered_data_len(uart_num, (size_t*)&length));
length = uart_read_bytes(uart_num, data, length, 100);

If the data in Rx FIFO is not required and should be discarded, call uart_flush().

Software Flow Control

When the hardware flow control is disabled, then use uart_set_rts() and uart_set_dtr() to manually set the levels of the RTS and DTR signals.

Communication Mode Selection

The UART controller supports set of communication modes. The selection of mode can be performed using function uart_set_mode(). Once the specific mode is selected the UART driver will handle behavior of external peripheral according to mode. As an example it can control RS485 driver chip over RTS line to allow half-duplex RS485 communication.

// Setup UART in rs485 half duplex mode
ESP_ERROR_CHECK(uart_set_mode(uart_num, UART_MODE_RS485_HALF_DUPLEX));

Using Interrupts

There are nineteen interrupts reported on specific states of UART or on detected errors. The full list of available interrupts is described in ESP32 Technical Reference Manual (PDF). To enable specific interrupts call uart_enable_intr_mask(), to disable call uart_disable_intr_mask(). The mask of all interrupts is available as UART_INTR_MASK. Registration of an handler to service interrupts is done with uart_isr_register(), freeing the handler with uart_isr_free(). To clear the interrupt status bits once the handler is called use uart_clear_intr_status().

The API provides a convenient way to handle specific interrupts discussed above by wrapping them into dedicated functions:

  • Event detection - there are several events defined in uart_event_type_t that may be reported to user application using FreeRTOS queue functionality. You can enable this functionality when calling uart_driver_install() described in Driver Installation. Example how to use it is covered in peripherals/uart_events.
  • FIFO space threshold or transmission timeout reached - the interrupts on TX or Rx FIFO buffer being filled with specific number of characters or on a timeout of sending or receiving data. To use these interrupts, first configure respective threshold values of the buffer length and the timeout by entering them in uart_intr_config_t structure and calling uart_intr_config(). Then enable interrupts with functions uart_enable_rx_intr() and uart_enable_tx_intr(). To disable these interrupts there are corresponding functions uart_disable_rx_intr() or uart_disable_tx_intr().
  • Pattern detection - an interrupt triggered on detecting a ‘pattern’ of the same character being sent number of times. The functions that allow to configure, enable and disable this interrupt are uart_enable_pattern_det_intr() and cpp:func:uart_disable_pattern_det_intr.

Macros

The API provides several macros to define configuration parameters, e.g. UART_FIFO_LEN to define the length of the hardware FIFO buffers, UART_BITRATE_MAX that gives the maximum baud rate supported by UART, etc.

Deleting Driver

If communication is established with uart_driver_install() for some specific period of time and then not required, the driver may be removed to free allocated resources by calling uart_driver_delete().

Overview of RS485 specific communication options

注解

Here and below the notation UART_REGISTER.UART_OPTION_BIT will be used to describe register options of UART. See the ESP32 Technical Reference Manual for more information.

  • UART_RS485_CONF_REG.UART_RS485_EN = 1, enable RS485 communication mode support.
  • UART_RS485_CONF_REG.UART_RS485TX_RX_EN, transmitter’s output signal loop back to the receiver’s input signal when this bit is set.
  • UART_RS485_CONF_REG.UART_RS485RXBY_TX_EN, when bit is set the transmitter should send data when its receiver is busy (remove collisions automatically by hardware).

The on chip RS485 UART hardware is able to detect signal collisions during transmission of datagram and generate an interrupt UART_RS485_CLASH_INT when it is enabled. The term collision means that during transmission of datagram the received data is different with what has been transmitted out or framing errors exist. Data collisions are usually associated with the presence of other active devices on the bus or due to bus errors. The collision detection feature allows suppressing the collisions when its interrupt is activated and triggered. The UART_RS485_FRM_ERR_INT and UART_RS485_PARITY_ERR_INT interrupts can be used with collision detection feature to control frame errors and parity errors accordingly in RS485 mode. This functionality is supported in the UART driver and can be used with selected UART_MODE_RS485_A mode (see uart_set_mode() function). The collision detection option can work with circuit A and circuit C (see below) which allow collision detection. In case of using circuit number A or B, control of RTS pin connected to DE pin of bus driver should be provided manually by application. The function uart_get_collision_flag() allows to get collision detection flag from driver.

The ESP32 UART hardware is not able to control automatically the RTS pin connected to ~RE/DE input of RS485 bus driver to provide half duplex communication. This can be done by UART driver software when UART_MODE_RS485_HALF_DUPLEX mode is selected using uart_set_mode() function. The UART driver software automatically asserts the RTS pin (logic 1) once the host writes data to the transmit FIFO, and deasserts RTS pin (logic 0) once the last bit of the data has been transmitted. To use this mode the software would have to disable the hardware flow control function. This mode works with any of used circuit showed below.

Overview of RS485 interface connection options

注解

The example schematics below are prepared for just demonstration of basic aspects of RS485 interface connection for ESP32 and may not contain all required elements. The Analog Devices ADM483 & ADM2483 are examples of common RS485 transceivers and other similar transceivers can also be used.

The circuit A: Collision detection circuit

        VCC ---------------+
                           |
                   +-------x-------+
        RXD <------| R             |
                   |              B|----------<> B
        TXD ------>| D    ADM483   |
ESP32              |               |     RS485 bus side
        RTS ------>| DE            |
                   |              A|----------<> A
              +----| /RE           |
              |    +-------x-------+
              |            |
             GND          GND

This circuit is preferred because it allows collision detection and is simple enough. The receiver in the line driver is constantly enabled that allows UART to monitor the RS485 bus. Echo suppression is done by the ESP32 chip hardware when the UART_RS485_CONF_REG.UART_RS485TX_RX_EN bit is enabled.

The circuit B: manual switching of transmitter/receiver without collision detection

        VCC ---------------+
                           |
                   +-------x-------+
        RXD <------| R             |
                   |              B|-----------<> B
        TXD ------>| D    ADM483   |
ESP32              |               |     RS485 bus side
        RTS --+--->| DE            |
              |    |              A|-----------<> A
              +----| /RE           |
                   +-------x-------+
                           |
                          GND

This circuit does not allow collision detection. It suppresses the null bytes receive by hardware when UART_RS485_CONF_REG.UART_RS485TX_RX_EN is set. The bit UART_RS485_CONF_REG.UART_RS485RXBY_TX_EN is not applicable in this case.

The circuit C: auto switching of transmitter/receiver

  VCC1<-------------------+-----------+           +-------------------+----> VCC2
               10K ____   |           |           |                   |
              +---|____|--+       +---x-----------x---+   10K  ____   |
              |                   |                   |   +---|____|--+ GND2
RX <----------+-------------------| RXD               |   |
                  10K  ____       |                  A|---+---------------<> A (+)
              +-------|____|------| PV    ADM2483     |   |    ____  120
              |   ____            |                   |   +---|____|---+  RS485 bus side
       VCC1<--+--|____|--+------->| DE                |                |
             10K         |        |                  B|---+------------+--<> B (-)
                      ---+    +-->| /RE               |   |    ____
        10K           |       |   |                   |   +---|____|---+
        ____       | /-C      +---| TXD               |   10K          |
TX >---|____|--B___|/   NPN   |   |                   |                |
                   |\         |   +---x-----------x---+                |
                   | \-E      |       |           |                    |
                      |       |       |           |                    |
                     GND1    GND1    GND1        GND2                 GND2

This galvanic isolated circuit does not require RTS pin control by software application or driver because it controls transceiver direction automatically. However it requires removing null bytes during transmission by setting UART_RS485_CONF_REG.UART_RS485RXBY_TX_EN = 1, UART_RS485_CONF_REG.UART_RS485TX_RX_EN = 0. This variant can work in any RS485 UART mode or even in UART_MODE_UART.

Application Examples

Configure UART settings and install UART driver to read/write using UART1 interface: peripherals/uart/uart_echo.

Demonstration of how to report various communication events and how to use patern detection interrupts: peripherals/uart/uart_events.

Transmitting and receiveing with the same UART in two separate FreeRTOS tasks: peripherals/uart/uart_async_rxtxtasks.

Using synchronous I/O multiplexing for UART file descriptors: peripherals/uart/uart_select.

Setup of UART driver to communicate over RS485 interface in half-duplex mode: peripherals/uart/uart_echo_rs485. This example is similar to uart_echo but provide communication through RS485 interface chip connected to ESP32 pins.

Demonstration of how to get GPS information by parsing NMEA0183 statements received from GPS via UART peripheral: peripherals/uart/nmea0183_parser.

API Reference

Functions

bool uart_is_driver_installed(uart_port_t uart_num)

Checks whether the driver is installed or not.

Return
  • true driver is installed
  • false driver is not installed
Parameters
  • uart_num: UART port number, the max port number is (UART_NUM_MAX -1).

esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit)

Set UART data bits.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • data_bit: UART data bits

esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t *data_bit)

Get UART data bits.

Return
  • ESP_FAIL Parameter error
  • ESP_OK Success, result will be put in (*data_bit)
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • data_bit: Pointer to accept value of UART data bits.

esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits)

Set UART stop bits.

Return
  • ESP_OK Success
  • ESP_FAIL Fail
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • stop_bits: UART stop bits

esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t *stop_bits)

Get UART stop bits.

Return
  • ESP_FAIL Parameter error
  • ESP_OK Success, result will be put in (*stop_bit)
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • stop_bits: Pointer to accept value of UART stop bits.

esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode)

Set UART parity mode.

Return
  • ESP_FAIL Parameter error
  • ESP_OK Success
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • parity_mode: the enum of uart parity configuration

esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t *parity_mode)

Get UART parity mode.

Return
  • ESP_FAIL Parameter error
  • ESP_OK Success, result will be put in (*parity_mode)
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • parity_mode: Pointer to accept value of UART parity mode.

esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate)

Set UART baud rate.

Return
  • ESP_FAIL Parameter error
  • ESP_OK Success
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • baudrate: UART baud rate.

esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t *baudrate)

Get UART baud rate.

Return
  • ESP_FAIL Parameter error
  • ESP_OK Success, result will be put in (*baudrate)
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • baudrate: Pointer to accept value of UART baud rate

esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask)

Set UART line inverse mode.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • inverse_mask: Choose the wires that need to be inverted. Inverse_mask should be chosen from UART_INVERSE_RXD / UART_INVERSE_TXD / UART_INVERSE_RTS / UART_INVERSE_CTS, combined with OR operation.

esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh)

Set hardware flow control.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • flow_ctrl: Hardware flow control mode
  • rx_thresh: Threshold of Hardware RX flow control (0 ~ UART_FIFO_LEN). Only when UART_HW_FLOWCTRL_RTS is set, will the rx_thresh value be set.

esp_err_t uart_set_sw_flow_ctrl(uart_port_t uart_num, bool enable, uint8_t rx_thresh_xon, uint8_t rx_thresh_xoff)

Set software flow control.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • enable: switch on or off
  • rx_thresh_xon: low water mark
  • rx_thresh_xoff: high water mark

esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t *flow_ctrl)

Get hardware flow control mode.

Return
  • ESP_FAIL Parameter error
  • ESP_OK Success, result will be put in (*flow_ctrl)
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • flow_ctrl: Option for different flow control mode.

esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask)

Clear UART interrupt status.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • clr_mask: Bit mask of the interrupt status to be cleared. The bit mask should be composed from the fields of register UART_INT_CLR_REG.

esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask)

Set UART interrupt enable.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • enable_mask: Bit mask of the enable bits. The bit mask should be composed from the fields of register UART_INT_ENA_REG.

esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask)

Clear UART interrupt enable bits.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • disable_mask: Bit mask of the disable bits. The bit mask should be composed from the fields of register UART_INT_ENA_REG.

esp_err_t uart_enable_rx_intr(uart_port_t uart_num)

Enable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT)

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2

esp_err_t uart_disable_rx_intr(uart_port_t uart_num)

Disable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT)

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2

esp_err_t uart_disable_tx_intr(uart_port_t uart_num)

Disable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT)

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2

esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh)

Enable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT)

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • enable: 1: enable; 0: disable
  • thresh: Threshold of TX interrupt, 0 ~ UART_FIFO_LEN

esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void *), void *arg, int intr_alloc_flags, uart_isr_handle_t *handle, )

Register UART interrupt handler (ISR).

Note
UART ISR handler will be attached to the same CPU core that this function is running on.
Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • fn: Interrupt handler function.
  • arg: parameter for handler function
  • intr_alloc_flags: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
  • handle: Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.

esp_err_t uart_isr_free(uart_port_t uart_num)

Free UART interrupt handler registered by uart_isr_register. Must be called on the same core as uart_isr_register was called.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2

esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num)

Set UART pin number.

Note
Internal signal can be output to multiple GPIO pads. Only one GPIO pad can connect with input signal.
Note
Instead of GPIO number a macro ‘UART_PIN_NO_CHANGE’ may be provided to keep the currently allocated pin.
Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • tx_io_num: UART TX pin GPIO number.
  • rx_io_num: UART RX pin GPIO number.
  • rts_io_num: UART RTS pin GPIO number.
  • cts_io_num: UART CTS pin GPIO number.

esp_err_t uart_set_rts(uart_port_t uart_num, int level)

Manually set the UART RTS pin level.

Note
UART must be configured with hardware flow control disabled.
Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • level: 1: RTS output low (active); 0: RTS output high (block)

esp_err_t uart_set_dtr(uart_port_t uart_num, int level)

Manually set the UART DTR pin level.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • level: 1: DTR output low; 0: DTR output high

esp_err_t uart_set_tx_idle_num(uart_port_t uart_num, uint16_t idle_num)

Set UART idle interval after tx FIFO is empty.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • idle_num: idle interval after tx FIFO is empty(unit: the time it takes to send one bit under current baudrate)

esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config)

Set UART configuration parameters.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • uart_config: UART parameter settings

esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf)

Configure UART interrupts.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • intr_conf: UART interrupt settings

esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue, int intr_alloc_flags)

Install UART driver.

UART ISR handler will be attached to the same CPU core that this function is running on.

Note
Rx_buffer_size should be greater than UART_FIFO_LEN. Tx_buffer_size should be either zero or greater than UART_FIFO_LEN.
Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • rx_buffer_size: UART RX ring buffer size.
  • tx_buffer_size: UART TX ring buffer size. If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out.
  • queue_size: UART event queue size/depth.
  • uart_queue: UART event queue handle (out param). On success, a new queue handle is written here to provide access to UART events. If set to NULL, driver will not use an event queue.
  • intr_alloc_flags: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. Do not set ESP_INTR_FLAG_IRAM here (the driver’s ISR handler is not located in IRAM)

esp_err_t uart_driver_delete(uart_port_t uart_num)

Uninstall UART driver.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2

esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait)

Wait until UART TX FIFO is empty.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
  • ESP_ERR_TIMEOUT Timeout
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • ticks_to_wait: Timeout, count in RTOS ticks

int uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len)

Send data to the UART port from a given buffer and length.

This function will not wait for enough space in TX FIFO. It will just fill the available TX FIFO and return when the FIFO is full.

Note
This function should only be used when UART TX buffer is not enabled.
Return
  • (-1) Parameter error
  • OTHERS (>=0) The number of bytes pushed to the TX FIFO
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • buffer: data buffer address
  • len: data length to send

int uart_write_bytes(uart_port_t uart_num, const char *src, size_t size)

Send data to the UART port from a given buffer and length,.

If the UART driver’s parameter ‘tx_buffer_size’ is set to zero: This function will not return until all the data have been sent out, or at least pushed into TX FIFO.

Otherwise, if the ‘tx_buffer_size’ > 0, this function will return after copying all the data to tx ring buffer, UART ISR will then move data from the ring buffer to TX FIFO gradually.

Return
  • (-1) Parameter error
  • OTHERS (>=0) The number of bytes pushed to the TX FIFO
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • src: data buffer address
  • size: data length to send

int uart_write_bytes_with_break(uart_port_t uart_num, const char *src, size_t size, int brk_len)

Send data to the UART port from a given buffer and length,.

If the UART driver’s parameter ‘tx_buffer_size’ is set to zero: This function will not return until all the data and the break signal have been sent out. After all data is sent out, send a break signal.

Otherwise, if the ‘tx_buffer_size’ > 0, this function will return after copying all the data to tx ring buffer, UART ISR will then move data from the ring buffer to TX FIFO gradually. After all data sent out, send a break signal.

Return
  • (-1) Parameter error
  • OTHERS (>=0) The number of bytes pushed to the TX FIFO
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • src: data buffer address
  • size: data length to send
  • brk_len: break signal duration(unit: the time it takes to send one bit at current baudrate)

int uart_read_bytes(uart_port_t uart_num, uint8_t *buf, uint32_t length, TickType_t ticks_to_wait)

UART read bytes from UART buffer.

Return
  • (-1) Error
  • OTHERS (>=0) The number of bytes read from UART FIFO
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2
  • buf: pointer to the buffer.
  • length: data length
  • ticks_to_wait: sTimeout, count in RTOS ticks

esp_err_t uart_flush(uart_port_t uart_num)

Alias of uart_flush_input. UART ring buffer flush. This will discard all data in the UART RX buffer.

Note
Instead of waiting the data sent out, this function will clear UART rx buffer. In order to send all the data in tx FIFO, we can use uart_wait_tx_done function.
Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2

esp_err_t uart_flush_input(uart_port_t uart_num)

Clear input buffer, discard all the data is in the ring-buffer.

Note
In order to send all the data in tx FIFO, we can use uart_wait_tx_done function.
Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART_NUM_0, UART_NUM_1 or UART_NUM_2

esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t *size)

UART get RX ring buffer cached data length.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART port number.
  • size: Pointer of size_t to accept cached data length

esp_err_t uart_disable_pattern_det_intr(uart_port_t uart_num)

UART disable pattern detect function. Designed for applications like ‘AT commands’. When the hardware detects a series of one same character, the interrupt will be triggered.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART port number.

esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle)

UART enable pattern detect function. Designed for applications like ‘AT commands’. When the hardware detect a series of one same character, the interrupt will be triggered.

Return
  • ESP_OK Success
  • ESP_FAIL Parameter error
Parameters
  • uart_num: UART port number.
  • pattern_chr: character of the pattern
  • chr_num: number of the character, 8bit value.
  • chr_tout: timeout of the interval between each pattern characters, 24bit value, unit is APB (80Mhz) clock cycle. When the duration is less than this value, it will not take this data as at_cmd char
  • post_idle: idle time after the last pattern character, 24bit value, unit is APB (80Mhz) clock cycle. When the duration is less than this value, it will not take the previous data as the last at_cmd char
  • pre_idle: idle time before the first pattern character, 24bit value, unit is APB (80Mhz) clock cycle. When the duration is less than this value, it will not take this data as the first at_cmd char

int uart_pattern_pop_pos(uart_port_t uart_num)

Return the nearest detected pattern position in buffer. The positions of the detected pattern are saved in a queue, this function will dequeue the first pattern position and move the pointer to next pattern position.

The following APIs will modify the pattern position info: uart_flush_input, uart_read_bytes, uart_driver_delete, uart_pop_pattern_pos It is the application’s responsibility to ensure atomic access to the pattern queue and the rx data buffer when using pattern detect feature.

Note
If the RX buffer is full and flow control is not enabled, the detected pattern may not be found in the rx buffer due to overflow.

Return
  • (-1) No pattern found for current index or parameter error
  • others the pattern position in rx buffer.
Parameters
  • uart_num: UART port number

int uart_pattern_get_pos(uart_port_t uart_num)

Return the nearest detected pattern position in buffer. The positions of the detected pattern are saved in a queue, This function do nothing to the queue.

The following APIs will modify the pattern position info: uart_flush_input, uart_read_bytes, uart_driver_delete, uart_pop_pattern_pos It is the application’s responsibility to ensure atomic access to the pattern queue and the rx data buffer when using pattern detect feature.

Note
If the RX buffer is full and flow control is not enabled, the detected pattern may not be found in the rx buffer due to overflow.

Return
  • (-1) No pattern found for current index or parameter error
  • others the pattern position in rx buffer.
Parameters
  • uart_num: UART port number

esp_err_t uart_pattern_queue_reset(uart_port_t uart_num, int queue_length)

Allocate a new memory with the given length to save record the detected pattern position in rx buffer.

Return
  • ESP_ERR_NO_MEM No enough memory
  • ESP_ERR_INVALID_STATE Driver not installed
  • ESP_FAIL Parameter error
  • ESP_OK Success
Parameters
  • uart_num: UART port number
  • queue_length: Max queue length for the detected pattern. If the queue length is not large enough, some pattern positions might be lost. Set this value to the maximum number of patterns that could be saved in data buffer at the same time.

esp_err_t uart_set_mode(uart_port_t uart_num, uart_mode_t mode)

UART set communication mode.

Note
This function must be executed after uart_driver_install(), when the driver object is initialized.
Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • uart_num: Uart number to configure
  • mode: UART UART mode to set

esp_err_t uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh)

UART set threshold timeout for TOUT feature.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
  • ESP_ERR_INVALID_STATE Driver is not installed
Parameters
  • uart_num: Uart number to configure
  • tout_thresh: This parameter defines timeout threshold in uart symbol periods. The maximum value of threshold is 126. tout_thresh = 1, defines TOUT interrupt timeout equal to transmission time of one symbol (~11 bit) on current baudrate. If the time is expired the UART_RXFIFO_TOUT_INT interrupt is triggered. If tout_thresh == 0, the TOUT feature is disabled.

esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool *collision_flag)

Returns collision detection flag for RS485 mode Function returns the collision detection flag into variable pointed by collision_flag. *collision_flag = true, if collision detected else it is equal to false. This function should be executed when actual transmission is completed (after uart_write_bytes()).

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • uart_num: Uart number to configure
  • collision_flag: Pointer to variable of type bool to return collision flag.

esp_err_t uart_set_wakeup_threshold(uart_port_t uart_num, int wakeup_threshold)

Set the number of RX pin signal edges for light sleep wakeup.

UART can be used to wake up the system from light sleep. This feature works by counting the number of positive edges on RX pin and comparing the count to the threshold. When the count exceeds the threshold, system is woken up from light sleep. This function allows setting the threshold value.

Stop bit and parity bits (if enabled) also contribute to the number of edges. For example, letter ‘a’ with ASCII code 97 is encoded as 0100001101 on the wire (with 8n1 configuration), start and stop bits included. This sequence has 3 positive edges (transitions from 0 to 1). Therefore, to wake up the system when ‘a’ is sent, set wakeup_threshold=3.

The character that triggers wakeup is not received by UART (i.e. it can not be obtained from UART FIFO). Depending on the baud rate, a few characters after that will also not be received. Note that when the chip enters and exits light sleep mode, APB frequency will be changing. To make sure that UART has correct baud rate all the time, select REF_TICK as UART clock source, by setting use_ref_tick field in uart_config_t to true.

Note
in ESP32, the wakeup signal can only be input via IO_MUX (i.e. GPIO3 should be configured as function_1 to wake up UART0, GPIO9 should be configured as function_5 to wake up UART1), UART2 does not support light sleep wakeup feature.
Return
  • ESP_OK on success
  • ESP_ERR_INVALID_ARG if uart_num is incorrect or wakeup_threshold is outside of [3, 0x3ff] range.
Parameters
  • uart_num: UART number
  • wakeup_threshold: number of RX edges for light sleep wakeup, value is 3 .. 0x3ff.

esp_err_t uart_get_wakeup_threshold(uart_port_t uart_num, int *out_wakeup_threshold)

Get the number of RX pin signal edges for light sleep wakeup.

See description of uart_set_wakeup_threshold for the explanation of UART wakeup feature.

Return
  • ESP_OK on success
  • ESP_ERR_INVALID_ARG if out_wakeup_threshold is NULL
Parameters
  • uart_num: UART number
  • out_wakeup_threshold: output, set to the current value of wakeup threshold for the given UART.

Structures

struct uart_config_t

UART configuration parameters for uart_param_config function.

Public Members

int baud_rate

UART baud rate

uart_word_length_t data_bits

UART byte size

uart_parity_t parity

UART parity mode

uart_stop_bits_t stop_bits

UART stop bits

uart_hw_flowcontrol_t flow_ctrl

UART HW flow control mode (cts/rts)

uint8_t rx_flow_ctrl_thresh

UART HW RTS threshold

bool use_ref_tick

Set to true if UART should be clocked from REF_TICK

struct uart_intr_config_t

UART interrupt configuration parameters for uart_intr_config function.

Public Members

uint32_t intr_enable_mask

UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator

uint8_t rx_timeout_thresh

UART timeout interrupt threshold (unit: time of sending one byte)

uint8_t txfifo_empty_intr_thresh

UART TX empty interrupt threshold.

uint8_t rxfifo_full_thresh

UART RX full interrupt threshold.

struct uart_event_t

Event structure used in UART event queue.

Public Members

uart_event_type_t type

UART event type

size_t size

UART data size for UART_DATA event

Macros

UART_FIFO_LEN

Length of the hardware FIFO buffers

UART_INTR_MASK

Mask of all UART interrupts

UART_LINE_INV_MASK

TBD

UART_BITRATE_MAX

Max bit rate supported by UART

UART_PIN_NO_CHANGE

Constant for uart_set_pin function which indicates that UART pin should not be changed

UART_INVERSE_DISABLE

Disable UART signal inverse

UART_INVERSE_RXD

UART RXD input inverse

UART_INVERSE_CTS

UART CTS input inverse

UART_INVERSE_TXD

UART TXD output inverse

UART_INVERSE_RTS

UART RTS output inverse

Type Definitions

typedef intr_handle_t uart_isr_handle_t

Enumerations

enum uart_mode_t

UART mode selection.

Values:

UART_MODE_UART = 0x00

mode: regular UART mode

UART_MODE_RS485_HALF_DUPLEX = 0x01

mode: half duplex RS485 UART mode control by RTS pin

UART_MODE_IRDA = 0x02

mode: IRDA UART mode

UART_MODE_RS485_COLLISION_DETECT = 0x03

mode: RS485 collision detection UART mode (used for test purposes)

UART_MODE_RS485_APP_CTRL = 0x04

mode: application control RS485 UART mode (used for test purposes)

enum uart_word_length_t

UART word length constants.

Values:

UART_DATA_5_BITS = 0x0

word length: 5bits

UART_DATA_6_BITS = 0x1

word length: 6bits

UART_DATA_7_BITS = 0x2

word length: 7bits

UART_DATA_8_BITS = 0x3

word length: 8bits

UART_DATA_BITS_MAX = 0x4
enum uart_stop_bits_t

UART stop bits number.

Values:

UART_STOP_BITS_1 = 0x1

stop bit: 1bit

UART_STOP_BITS_1_5 = 0x2

stop bit: 1.5bits

UART_STOP_BITS_2 = 0x3

stop bit: 2bits

UART_STOP_BITS_MAX = 0x4
enum uart_port_t

UART peripheral number.

Values:

UART_NUM_0 = 0x0

UART base address 0x3ff40000

UART_NUM_1 = 0x1

UART base address 0x3ff50000

UART_NUM_MAX
enum uart_parity_t

UART parity constants.

Values:

UART_PARITY_DISABLE = 0x0

Disable UART parity

UART_PARITY_EVEN = 0x2

Enable UART even parity

UART_PARITY_ODD = 0x3

Enable UART odd parity

enum uart_hw_flowcontrol_t

UART hardware flow control modes.

Values:

UART_HW_FLOWCTRL_DISABLE = 0x0

disable hardware flow control

UART_HW_FLOWCTRL_RTS = 0x1

enable RX hardware flow control (rts)

UART_HW_FLOWCTRL_CTS = 0x2

enable TX hardware flow control (cts)

UART_HW_FLOWCTRL_CTS_RTS = 0x3

enable hardware flow control

UART_HW_FLOWCTRL_MAX = 0x4
enum uart_event_type_t

UART event types used in the ring buffer.

Values:

UART_DATA

UART data event

UART_BREAK

UART break event

UART_BUFFER_FULL

UART RX buffer full event

UART_FIFO_OVF

UART FIFO overflow event

UART_FRAME_ERR

UART RX frame error event

UART_PARITY_ERR

UART RX parity event

UART_DATA_BREAK

UART TX data and break event

UART_PATTERN_DET

UART pattern detected

UART_EVENT_MAX

UART event max index

GPIO Lookup Macros

You can use macros to specify the direct GPIO (UART module connected to pads through direct IO mux without the GPIO mux) number of a UART channel, or vice versa. The pin name can be omitted if the channel of a GPIO number is specified, e.g.:

  1. UART_NUM_2_TXD_DIRECT_GPIO_NUM is the GPIO number of UART channel 2 TXD pin (17);
  2. UART_GPIO19_DIRECT_CHANNEL is the UART channel number of GPIO 19 (channel 0);
  3. UART_CTS_GPIO19_DIRECT_CHANNEL is the UART channel number of GPIO 19, and GPIO 19 must be a CTS pin (channel 0).

Macros

UART_GPIO1_DIRECT_CHANNEL
UART_NUM_0_TXD_DIRECT_GPIO_NUM
UART_GPIO3_DIRECT_CHANNEL
UART_NUM_0_RXD_DIRECT_GPIO_NUM
UART_GPIO19_DIRECT_CHANNEL
UART_NUM_0_CTS_DIRECT_GPIO_NUM
UART_GPIO22_DIRECT_CHANNEL
UART_NUM_0_RTS_DIRECT_GPIO_NUM
UART_TXD_GPIO1_DIRECT_CHANNEL
UART_RXD_GPIO3_DIRECT_CHANNEL
UART_CTS_GPIO19_DIRECT_CHANNEL
UART_RTS_GPIO22_DIRECT_CHANNEL
UART_GPIO10_DIRECT_CHANNEL
UART_NUM_1_TXD_DIRECT_GPIO_NUM
UART_GPIO9_DIRECT_CHANNEL
UART_NUM_1_RXD_DIRECT_GPIO_NUM
UART_GPIO6_DIRECT_CHANNEL
UART_NUM_1_CTS_DIRECT_GPIO_NUM
UART_GPIO11_DIRECT_CHANNEL
UART_NUM_1_RTS_DIRECT_GPIO_NUM
UART_TXD_GPIO10_DIRECT_CHANNEL
UART_RXD_GPIO9_DIRECT_CHANNEL
UART_CTS_GPIO6_DIRECT_CHANNEL
UART_RTS_GPIO11_DIRECT_CHANNEL
UART_GPIO17_DIRECT_CHANNEL
UART_NUM_2_TXD_DIRECT_GPIO_NUM
UART_GPIO16_DIRECT_CHANNEL
UART_NUM_2_RXD_DIRECT_GPIO_NUM
UART_GPIO8_DIRECT_CHANNEL
UART_NUM_2_CTS_DIRECT_GPIO_NUM
UART_GPIO7_DIRECT_CHANNEL
UART_NUM_2_RTS_DIRECT_GPIO_NUM
UART_TXD_GPIO17_DIRECT_CHANNEL
UART_RXD_GPIO16_DIRECT_CHANNEL
UART_CTS_GPIO8_DIRECT_CHANNEL
UART_RTS_GPIO7_DIRECT_CHANNEL