1Universal Asynchronous Receiver/Transmitter (UART)
2==================================================
3
4{IDF_TARGET_UART_NUM:default = "UART_NUM_1", esp32 = "UART_NUM_2", esp32s3 = "UART_NUM_2"}
5
6Overview
7--------
8
9A Universal Asynchronous Receiver/Transmitter (UART) is a hardware feature that handles communication (i.e., timing requirements and data framing) using widely-adopted asynchronous serial communication interfaces, such as RS232, RS422, RS485. A UART provides a widely adopted and cheap method to realize full-duplex or half-duplex data exchange among different devices.
10
11.. only:: esp32 or esp32s3
12
13    The {IDF_TARGET_NAME} chip has three UART controllers (UART0, UART1, and UART2), each featuring an identical set of registers to simplify programming and for more flexibility.
14
15.. only:: esp32s2 or esp32c3
16
17    The {IDF_TARGET_NAME} chip has two UART controllers (UART0 and UART1), each featuring an identical set of registers to simplify programming and for more flexibility.
18
19Each UART controller is independently configurable with parameters such as baud rate, data bit length, bit ordering, number of stop bits, parity bit etc. All the controllers are compatible with UART-enabled devices from various manufacturers and can also support Infrared Data Association protocols (IrDA).
20
21Functional Overview
22-------------------
23
24The following overview describes how to establish communication between an {IDF_TARGET_NAME} and other UART devices using the functions and data types of the UART driver. The overview reflects a typical programming workflow and is broken down into the sections provided below:
25
261. :ref:`uart-api-setting-communication-parameters` - Setting baud rate, data bits, stop bits, etc.
272. :ref:`uart-api-setting-communication-pins` - Assigning pins for connection to a device.
283. :ref:`uart-api-driver-installation` - Allocating {IDF_TARGET_NAME}'s resources for the UART driver.
294. :ref:`uart-api-running-uart-communication` - Sending / receiving data
305. :ref:`uart-api-using-interrupts` - Triggering interrupts on specific communication events
316. :ref:`uart-api-deleting-driver` - Freeing allocated resources if a UART communication is no longer required
32
33Steps 1 to 3 comprise the configuration stage. Step 4 is where the UART starts operating. Steps 5 and 6 are optional.
34
35The UART driver's functions identify each of the UART controllers using :cpp:type:`uart_port_t`. This identification is needed for all the following function calls.
36
37
38.. _uart-api-setting-communication-parameters:
39
40Setting Communication Parameters
41^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42
43UART communication parameters can be configured all in a single step or individually in multiple steps.
44
45
46Single Step
47"""""""""""
48
49Call the function :cpp:func:`uart_param_config` and pass to it a :cpp:type:`uart_config_t` structure. The :cpp:type:`uart_config_t` structure should contain all the required parameters. See the example below.
50
51.. code-block:: c
52
53    const uart_port_t uart_num = {IDF_TARGET_UART_NUM};
54    uart_config_t uart_config = {
55        .baud_rate = 115200,
56        .data_bits = UART_DATA_8_BITS,
57        .parity = UART_PARITY_DISABLE,
58        .stop_bits = UART_STOP_BITS_1,
59        .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
60        .rx_flow_ctrl_thresh = 122,
61    };
62    // Configure UART parameters
63    ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));
64
65
66Multiple Steps
67""""""""""""""
68
69Configure specific parameters individually by calling a dedicated function from the table given below. These functions are also useful if re-configuring a single parameter.
70
71.. list-table:: Functions for Configuring specific parameters individually
72   :widths: 30 70
73   :header-rows: 1
74
75   * - Parameter to Configure
76     - Function
77   * - Baud rate
78     - :cpp:func:`uart_set_baudrate`
79   * - Number of transmitted bits
80     - :cpp:func:`uart_set_word_length` selected out of :cpp:type:`uart_word_length_t`
81   * - Parity control
82     - :cpp:func:`uart_set_parity` selected out of :cpp:type:`uart_parity_t`
83   * - Number of stop bits
84     - :cpp:func:`uart_set_stop_bits` selected out of :cpp:type:`uart_stop_bits_t`
85   * - Hardware flow control mode
86     - :cpp:func:`uart_set_hw_flow_ctrl` selected out of :cpp:type:`uart_hw_flowcontrol_t`
87   * - Communication mode
88     - :cpp:func:`uart_set_mode` selected out of :cpp:type:`uart_mode_t`
89
90Each of the above functions has a ``_get_`` counterpart to check the currently set value. For example, to check the current baud rate value, call :cpp:func:`uart_get_baudrate`.
91
92
93.. _uart-api-setting-communication-pins:
94
95Setting Communication Pins
96^^^^^^^^^^^^^^^^^^^^^^^^^^
97
98After setting communication parameters, configure the physical GPIO pins to which the other UART device will be connected. For this, call the function :cpp:func:`uart_set_pin` and specify the GPIO pin numbers to which the driver should route the Tx, Rx, RTS, and CTS signals. If you want to keep a currently allocated pin number for a specific signal, pass the macro :c:macro:`UART_PIN_NO_CHANGE`.
99
100The same macro should be specified for pins that will not be used.
101
102.. code-block:: c
103
104  // Set UART pins(TX: IO4, RX: IO5, RTS: IO18, CTS: IO19)
105  ESP_ERROR_CHECK(uart_set_pin({IDF_TARGET_UART_NUM}, 4, 5, 18, 19));
106
107.. _uart-api-driver-installation:
108
109Driver Installation
110^^^^^^^^^^^^^^^^^^^
111
112Once the communication pins are set, install the driver by calling :cpp:func:`uart_driver_install` and specify the following parameters:
113
114- Size of Tx ring buffer
115- Size of Rx ring buffer
116- Event queue handle and size
117- Flags to allocate an interrupt
118
119The function will allocate the required internal resources for the UART driver.
120
121.. code-block:: c
122
123    // Setup UART buffered IO with event queue
124    const int uart_buffer_size = (1024 * 2);
125    QueueHandle_t uart_queue;
126    // Install UART driver using an event queue here
127    ESP_ERROR_CHECK(uart_driver_install({IDF_TARGET_UART_NUM}, uart_buffer_size, \
128                                            uart_buffer_size, 10, &uart_queue, 0));
129
130Once this step is complete, you can connect the external UART device and check the communication.
131
132
133.. _uart-api-running-uart-communication:
134
135Running UART Communication
136^^^^^^^^^^^^^^^^^^^^^^^^^^
137
138Serial communication is controlled by each UART controller's finite state machine (FSM).
139
140The process of sending data involves the following steps:
141
1421. Write data into Tx FIFO buffer
1432. FSM serializes the data
1443. FSM sends the data out
145
146The process of receiving data is similar, but the steps are reversed:
147
1481. FSM processes an incoming serial stream and parallelizes it
1492. FSM writes the data into Rx FIFO buffer
1503. Read the data from Rx FIFO buffer
151
152Therefore, an application will be limited to writing and reading data from a respective buffer using :cpp:func:`uart_write_bytes` and :cpp:func:`uart_read_bytes` respectively, and the FSM will do the rest.
153
154
155Transmitting
156""""""""""""
157
158After preparing the data for transmission, call the function :cpp:func:`uart_write_bytes` and pass the data buffer's address and data length to it. The function will copy the data to the Tx ring buffer (either immediately or after enough space is available), and then exit. When there is free space in the Tx FIFO buffer, an interrupt service routine (ISR) moves the data from the Tx ring buffer to the Tx FIFO buffer in the background. The code below demonstrates the use of this function.
159
160.. code-block:: c
161
162    // Write data to UART.
163    char* test_str = "This is a test string.\n";
164    uart_write_bytes(uart_num, (const char*)test_str, strlen(test_str));
165
166The function :cpp:func:`uart_write_bytes_with_break` is similar to :cpp:func:`uart_write_bytes` but adds a serial break signal at the end of the transmission. A 'serial break signal' means holding the Tx line low for a period longer than one data frame.
167
168.. code-block:: c
169
170    // Write data to UART, end with a break signal.
171    uart_write_bytes_with_break(uart_num, "test break\n",strlen("test break\n"), 100);
172
173Another function for writing data to the Tx FIFO buffer is :cpp:func:`uart_tx_chars`. Unlike :cpp:func:`uart_write_bytes`, this function will not block until space is available. Instead, it will write all data which can immediately fit into the hardware Tx FIFO, and then return the number of bytes that were written.
174
175There is a 'companion' function :cpp:func:`uart_wait_tx_done` that monitors the status of the Tx FIFO buffer and returns once it is empty.
176
177.. code-block:: c
178
179    // Wait for packet to be sent
180    const uart_port_t uart_num = {IDF_TARGET_UART_NUM};
181    ESP_ERROR_CHECK(uart_wait_tx_done(uart_num, 100)); // wait timeout is 100 RTOS ticks (TickType_t)
182
183
184Receiving
185"""""""""
186
187Once the data is received by the UART and saved in the Rx FIFO buffer, it needs to be retrieved using the function :cpp:func:`uart_read_bytes`. Before reading data, you can check the number of bytes available in the Rx FIFO buffer by calling :cpp:func:`uart_get_buffered_data_len`. An example of using these functions is given below.
188
189.. code-block:: c
190
191    // Read data from UART.
192    const uart_port_t uart_num = {IDF_TARGET_UART_NUM};
193    uint8_t data[128];
194    int length = 0;
195    ESP_ERROR_CHECK(uart_get_buffered_data_len(uart_num, (size_t*)&length));
196    length = uart_read_bytes(uart_num, data, length, 100);
197
198If the data in the Rx FIFO buffer is no longer needed, you can clear the buffer by calling :cpp:func:`uart_flush`.
199
200
201Software Flow Control
202"""""""""""""""""""""
203
204If the hardware flow control is disabled, you can manually set the RTS and DTR signal levels by using the functions :cpp:func:`uart_set_rts` and :cpp:func:`uart_set_dtr` respectively.
205
206
207Communication Mode Selection
208""""""""""""""""""""""""""""
209
210The UART controller supports a number of communication modes. A mode can be selected using the function :cpp:func:`uart_set_mode`. Once a specific mode is selected, the UART driver will handle the behavior of a connected UART device accordingly. As an example, it can control the RS485 driver chip using the RTS line to allow half-duplex RS485 communication.
211
212.. code-block:: bash
213
214    // Setup UART in rs485 half duplex mode
215    ESP_ERROR_CHECK(uart_set_mode(uart_num, UART_MODE_RS485_HALF_DUPLEX));
216
217
218.. _uart-api-using-interrupts:
219
220Using Interrupts
221^^^^^^^^^^^^^^^^
222
223There are many interrupts that can be generated following specific UART states or detected errors. The full list of available interrupts is provided in *{IDF_TARGET_NAME} Technical Reference Manual* > *UART Controller (UART)* > *UART Interrupts* and *UHCI Interrupts* [`PDF <{IDF_TARGET_TRM_EN_URL}#uart>`__]. You can enable or disable specific interrupts by calling :cpp:func:`uart_enable_intr_mask` or :cpp:func:`uart_disable_intr_mask` respectively. The mask of all interrupts is available as :c:macro:`UART_INTR_MASK`.
224
225By default, the :cpp:func:`uart_driver_install` function installs the driver's internal interrupt handler to manage the Tx and Rx ring buffers and provides high-level API functions like events (see below). It is also possible to register a lower level interrupt handler instead using :cpp:func:`uart_isr_register`, and to free it again using :cpp:func:`uart_isr_free`. Some UART driver functions which use the Tx and Rx ring buffers, events, etc. will not automatically work in this case - it is necessary to handle the interrupts directly in the ISR. Inside the custom handler implementation, clear the interrupt status bits using :cpp:func:`uart_clear_intr_status`.
226
227The API provides a convenient way to handle specific interrupts discussed in this document by wrapping them into dedicated functions:
228
229- **Event detection**: There are several events defined in :cpp:type:`uart_event_type_t` that may be reported to a user application using the FreeRTOS queue functionality. You can enable this functionality when calling :cpp:func:`uart_driver_install` described in :ref:`uart-api-driver-installation`. An example of using Event detection can be found in :example:`peripherals/uart/uart_events`.
230
231- **FIFO space threshold or transmission timeout reached**: The Tx and Rx FIFO buffers can trigger an interrupt when they are filled with a specific number of characters, or on a timeout of sending or receiving data. To use these interrupts, do the following:
232
233    - Configure respective threshold values of the buffer length and timeout by entering them in the structure :cpp:type:`uart_intr_config_t` and calling :cpp:func:`uart_intr_config`
234    - Enable the interrupts using the functions :cpp:func:`uart_enable_tx_intr` and :cpp:func:`uart_enable_rx_intr`
235    - Disable these interrupts using the corresponding functions :cpp:func:`uart_disable_tx_intr` or :cpp:func:`uart_disable_rx_intr`
236
237- **Pattern detection**: An interrupt triggered on detecting a 'pattern' of the same character being received/sent repeatedly for a number of times. This functionality is demonstrated in the example :example:`peripherals/uart/uart_events`. It can be used, e.g., to detect a command string followed by a specific number of identical characters (the 'pattern') added at the end of the command string. The following functions are available:
238
239    - Configure and enable this interrupt using :cpp:func:`uart_enable_pattern_det_intr`
240    - Disable the interrupt using :cpp:func:`uart_disable_pattern_det_intr`
241
242
243Macros
244^^^^^^
245
246The API also defines several macros. For example, :c:macro:`UART_FIFO_LEN` defines the length of hardware FIFO buffers; :c:macro:`UART_BITRATE_MAX` gives the maximum baud rate supported by the UART controllers, etc.
247
248
249.. _uart-api-deleting-driver:
250
251Deleting a Driver
252^^^^^^^^^^^^^^^^^
253
254If the communication established with :cpp:func:`uart_driver_install` is no longer required, the driver can be removed to free allocated resources by calling :cpp:func:`uart_driver_delete`.
255
256
257Overview of RS485 specific communication options
258------------------------------------------------
259
260.. note::
261
262    The following section will use ``[UART_REGISTER_NAME].[UART_FIELD_BIT]`` to refer to UART register fields/bits. For more information on a specific option bit, see *{IDF_TARGET_NAME} Technical Reference Manual* > *UART Controller (UART)* > *Register Summary* [`PDF <{IDF_TARGET_TRM_EN_URL}#uart-reg-summ>`__]. Use the register name to navigate to the register description and then find the field/bit.
263
264- ``UART_RS485_CONF_REG.UART_RS485_EN``: setting this bit enables RS485 communication mode support.
265- ``UART_RS485_CONF_REG.UART_RS485TX_RX_EN``: if this bit is set, the transmitter's output signal loops back to the receiver's input signal.
266- ``UART_RS485_CONF_REG.UART_RS485RXBY_TX_EN``: if this bit is set, the transmitter will still be sending data if the receiver is busy (remove collisions automatically by hardware).
267
268The {IDF_TARGET_NAME}'s RS485 UART hardware can detect signal collisions during transmission of a datagram and generate the interrupt ``UART_RS485_CLASH_INT`` if this interrupt is enabled. The term collision means that a transmitted datagram is not equal to the one received on the other end. Data collisions are usually associated with the presence of other active devices on the bus or might occur due to bus errors.
269
270The collision detection feature allows handling collisions when their interrupts are activated and triggered. The interrupts ``UART_RS485_FRM_ERR_INT`` and ``UART_RS485_PARITY_ERR_INT`` can be used with the collision detection feature to control frame errors and parity bit errors accordingly in RS485 mode. This functionality is supported in the UART driver and can be used by selecting the :cpp:enumerator:`UART_MODE_RS485_APP_CTRL` mode (see the function :cpp:func:`uart_set_mode`).
271
272The collision detection feature can work with circuit A and circuit C (see Section `Interface Connection Options`_). In the case of using circuit A or B, the RTS pin connected to the DE pin of the bus driver should be controlled by the user application. Use the function :cpp:func:`uart_get_collision_flag` to check if the collision detection flag has been raised.
273
274The {IDF_TARGET_NAME} UART controllers themselves do not support half-duplex communication as they cannot provide automatic control of the RTS pin connected to the ~RE/DE input of RS485 bus driver. However, half-duplex communication can be achieved via software control of the RTS pin by the UART driver. This can be enabled by selecting the :cpp:enumerator:`UART_MODE_RS485_HALF_DUPLEX` mode when calling :cpp:func:`uart_set_mode`.
275
276Once the host starts writing data to the Tx FIFO buffer, the UART driver automatically asserts the RTS pin (logic 1); once the last bit of the data has been transmitted, the driver de-asserts the RTS pin (logic 0). To use this mode, the software would have to disable the hardware flow control function. This mode works with all the used circuits shown below.
277
278
279Interface Connection Options
280^^^^^^^^^^^^^^^^^^^^^^^^^^^^
281
282This section provides example schematics to demonstrate the basic aspects of {IDF_TARGET_NAME}'s RS485 interface connection.
283
284.. note::
285
286    - The schematics below do **not** necessarily contain **all required elements**.
287
288    - The **analog devices** ADM483 & ADM2483 are examples of common RS485 transceivers and **can be replaced** with other similar transceivers.
289
290
291Circuit A: Collision Detection Circuit
292""""""""""""""""""""""""""""""""""""""
293
294.. code-block:: none
295
296         VCC ---------------+
297                            |
298                    +-------x-------+
299         RXD <------| R             |
300                    |              B|----------<> B
301         TXD ------>| D    ADM483   |
302 ESP                |               |     RS485 bus side
303         RTS ------>| DE            |
304                    |              A|----------<> A
305               +----| /RE           |
306               |    +-------x-------+
307               |            |
308              GND          GND
309
310This circuit is preferable because it allows for collision detection and is quite simple at the same time. The receiver in the line driver is constantly enabled, which allows the UART to monitor the RS485 bus. Echo suppression is performed by the UART peripheral when the bit ``UART_RS485_CONF_REG.UART_RS485TX_RX_EN`` is enabled.
311
312
313Circuit B: Manual Switching Transmitter/Receiver Without Collision Detection
314""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
315
316
317.. code-block:: none
318
319         VCC ---------------+
320                            |
321                    +-------x-------+
322         RXD <------| R             |
323                    |              B|-----------<> B
324         TXD ------>| D    ADM483   |
325 ESP                |               |     RS485 bus side
326         RTS --+--->| DE            |
327               |    |              A|-----------<> A
328               +----| /RE           |
329                    +-------x-------+
330                            |
331                           GND
332
333This circuit does not allow for collision detection. It suppresses the null bytes that the hardware receives when the bit ``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.
334
335
336Circuit C: Auto Switching Transmitter/Receiver
337""""""""""""""""""""""""""""""""""""""""""""""
338
339.. code-block:: none
340
341   VCC1 <-------------------+-----------+           +-------------------+----> VCC2
342                 10K ____   |           |           |                   |
343                +---|____|--+       +---x-----------x---+    10K ____   |
344                |                   |                   |   +---|____|--+
345  RX <----------+-------------------| RXD               |   |
346                     10K ____       |                  A|---+---------------<> A (+)
347                +-------|____|------| PV    ADM2483     |   |    ____  120
348                |   ____            |                   |   +---|____|---+  RS485 bus side
349        VCC1 <--+--|____|--+------->| DE                |                |
350                10K        |        |                  B|---+------------+--<> B (-)
351                        ---+    +-->| /RE               |   |    ____
352           10K          |       |   |                   |   +---|____|---+
353          ____       | /-C      +---| TXD               |    10K         |
354  TX >---|____|--+_B_|/   NPN   |   |                   |                |
355                     |\         |   +---x-----------x---+                |
356                     | \-E      |       |           |                    |
357                        |       |       |           |                    |
358                       GND1    GND1    GND1        GND2                 GND2
359
360This galvanically isolated circuit does not require RTS pin control by a software application or driver because it controls the transceiver direction automatically. However, it requires suppressing null bytes during transmission by setting ``UART_RS485_CONF_REG.UART_RS485RXBY_TX_EN`` to 1 and ``UART_RS485_CONF_REG.UART_RS485TX_RX_EN`` to 0. This setup can work in any RS485 UART mode or even in :cpp:enumerator:`UART_MODE_UART`.
361
362
363Application Examples
364--------------------
365
366The table below describes the code examples available in the directory :example:`peripherals/uart/`.
367
368.. list-table::
369   :widths: 35 65
370   :header-rows: 1
371
372   * - Code Example
373     - Description
374   * - :example:`peripherals/uart/uart_echo`
375     - Configuring UART settings, installing the UART driver, and reading/writing over the UART1 interface.
376   * - :example:`peripherals/uart/uart_events`
377     - Reporting various communication events, using pattern detection interrupts.
378   * - :example:`peripherals/uart/uart_async_rxtxtasks`
379     - Transmitting and receiving data in two separate FreeRTOS tasks over the same UART.
380   * - :example:`peripherals/uart/uart_select`
381     - Using synchronous I/O multiplexing for UART file descriptors.
382   * - :example:`peripherals/uart/uart_echo_rs485`
383     - Setting up UART driver to communicate over RS485 interface in half-duplex mode. This example is similar to :example:`peripherals/uart/uart_echo` but allows communication through an RS485 interface chip connected to {IDF_TARGET_NAME} pins.
384   * - :example:`peripherals/uart/nmea0183_parser`
385     - Obtaining GPS information by parsing NMEA0183 statements received from GPS via the UART peripheral.
386
387
388API Reference
389-------------
390
391.. include-build-file:: inc/uart.inc
392.. include-build-file:: inc/uart_types.inc
393
394
395GPIO Lookup Macros
396^^^^^^^^^^^^^^^^^^
397
398The UART peripherals have dedicated IO_MUX pins to which they are connected directly. However, signals can also be routed to other pins using the less direct GPIO matrix. To use direct routes, you need to know which pin is a dedicated IO_MUX pin for a UART channel. GPIO Lookup Macros simplify the process of finding and assigning IO_MUX pins. You choose a macro based on either the IO_MUX pin number, or a required UART channel name, and the macro will return the matching counterpart for you. See some examples below.
399
400.. note::
401
402    These macros are useful if you need very high UART baud rates (over 40 MHz), which means you will have to use IO_MUX pins only. In other cases, these macros can be ignored, and you can use the GPIO Matrix as it allows you to configure any GPIO pin for any UART function.
403
4041. :c:macro:`UART_NUM_2_TXD_DIRECT_GPIO_NUM` returns the IO_MUX pin number of UART channel 2 TXD pin (pin 17)
4052. :c:macro:`UART_GPIO19_DIRECT_CHANNEL` returns the UART number of GPIO 19 when connected to the UART peripheral via IO_MUX (this is UART_NUM_0)
4063. :c:macro:`UART_CTS_GPIO19_DIRECT_CHANNEL` returns the UART number of GPIO 19 when used as the UART CTS pin via IO_MUX (this is UART_NUM_0). Similar to the above macro but specifies the pin function which is also part of the IO_MUX assignment.
407
408.. include-build-file:: inc/uart_channel.inc
409
410