1# UART 2 3## Overview 4 5### Function 6 7The Universal Asynchronous Receiver/Transmitter (UART) is a universal serial data bus used for asynchronous communication. It enables bi-directional communication between devices in full-duplex mode. 8 9A UART is connected to other modules through two wires (as shown in Figure 1) or four wires (as shown in Figure 2). 10 11 - TX: UART transmitter. It is connected to the RX of the peer UART. 12 - RX: UART receiver. It is connected to the TX of the peer UART. 13 - RTS: Request to Send signal, indicating whether the local UART is ready to receive data. It is connected to the CTS of the peer UART. 14 - CTS: Clear to Send signal, indicating whether the local UART is allowed to send data to the peer end. It is connected to the RTS of the peer UART. 15 16**Figure 1** Two-wire UART communication 17 18![image1](figures/2-wire-uart-communication.png "2-wire-uart-communication") 19 20**Figure 2** Four-wire UART communication 21 22 ![image2](figures/4-wire-uart-communication.png "4-wire-uart-communication") 23 24The UART transmitter and receiver must have the same settings on particular attributes, such as the baud rate and data format (start bit, data bits, parity bit, and stop bit) before they start to communicate. A UART sends data to the peer end over the TX and receives data from the peer end over the RX. When the size of the buffer used by a UART for storing received data reaches the preset threshold, the RTS signal of the UART changes to **1** (data cannot be received), and the peer UART stops sending data to it because its CTS signal does not allow it to send data. 25 26The UART module provides APIs for operating UART ports, including: 27 28- Opening or closing a UART device 29- Reading or writing data 30- Setting or obtaining the baud rate of a UART device 31- Setting or obtaining UART device attributes 32 33### Basic Concepts 34 35- Asynchronous communication 36 37 In asynchronous communication, data is transmitted in frames of characters or bytes. Frames are sent and received one by one through the transmission line. The transmitter and receiver have their own clocks to control data sending and receiving. The two clock sources are independent and not synchronized with each other. 38 39 When data is sent one character at a time, the time interval between two characters is not fixed, but the time interval between two adjacent bits in a character frame is fixed. 40 41- Full-duplex transmission 42 43 A duplex communication mode allows data to be transmitted in both directions at the same time. A duplex communication channel is equivalent to two simplex communication channels operating in opposite directions at the same time. In full-duplex mode, signals can be transmitted bidirectionally at the same time. 44 45### Working Principles 46 47In the Hardware Driver Foundation (HDF), the UART uses the independent service mode (see Figure 3) for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device, which increases memory usage. 48 49In the independent service mode, the core layer does not publish a service for the upper layer. Therefore, a service must be published for each controller. To achieve this purpose: 50 51- You need to implement the **Bind()** function in **HdfDriverEntry** to bind services. 52- The **policy** field of **deviceNode** in the **device_info.hcs** file can be **1** or **2**, but not **0**. 53 54The UART module is divided into the following layers: 55 56- Interface layer: provides APIs for opening or closing a UART device, reading or writing data of the specified length, setting or obtaining the baud rate or attributes of a UART device, and setting the transmission mode. 57- Core layer: provides the capabilities of adding or removing a UART controller, and managing UART devices. The core layer interacts with the adaptation layer through hook functions. 58- Adaptation layer: instantiates the hook functions to implement specific features. 59 60**Figure 3** Independent service mode 61 62![image3](figures/independent-service-mode.png) 63 64## Usage Guidelines 65 66### When to Use 67 68The UART module is widely used to implement low-speed serial communication between devices, for example, output the printing information. It can also connect to a variety of external GPS and Bluetooth devices. 69 70### Available APIs 71 72**Table 1** UART driver APIs 73 74| API| Description| 75| -------- | -------- | 76| DevHandle UartOpen(uint32_t port) | Opens a UART device.| 77| void UartClose(DevHandle handle) | Closes a UART device.| 78| int32_t UartRead(DevHandle handle, uint8_t *data, uint32_t size) | Reads data of the specified length from a UART device.| 79| int32_t UartWrite(DevHandle handle, uint8_t *data, uint32_t size) | Writes data of the specified length to a UART device.| 80| int32_t UartGetBaud(DevHandle handle, uint32_t *baudRate) | Obtains the UART baud rate.| 81| int32_t UartSetBaud(DevHandle handle, uint32_t baudRate) | Sets the UART baud rate.| 82| int32_t UartGetAttribute(DevHandle handle, struct UartAttribute *attribute) | Obtains UART device attributes.| 83| int32_t UartSetAttribute(DevHandle handle, struct UartAttribute *attribute) | Sets UART device attributes.| 84| int32_t UartSetTransMode(DevHandle handle, enum UartTransMode mode) | Sets the UART transmission mode.| 85 86> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** 87> 88> All the UART APIs described in this document can be used in kernel mode and user mode. 89 90### How to Develop 91 92The following figure illustrates how to use the UART APIs. 93 94**Figure 4** Using UART driver APIs 95 96![image4](figures/using-UART-process.png) 97 98 99#### Opening a UART Device 100 101Before performing UART communication, use **UartOpen()** to obtain a UART device handle based on the port number. 102 103```c 104DevHandle UartOpen(uint32_t port); 105``` 106 107**Table 2** Description of UartOpen 108 109| Parameter| Description| 110| -------- | -------- | 111| port | UART port number.| 112| **Return Value**| **Description**| 113| NULL | The operation fails.| 114| Device handle| The operation is successful. The obtained UART device handle is returned.| 115 116Example: Obtain the device handle of UART port 1. 117 118```c 119DevHandle handle = NULL; // UART device handle. 120uint32_t port = 1; // UART device port number. 121 122handle = UartOpen(port); 123if (handle == NULL) { 124 HDF_LOGE("UartOpen: open uart_%u failed!\n", port); 125 return; 126} 127``` 128 129#### Setting the UART Baud Rate 130 131Use **UartSetBaud()** to set the UART baud rate. 132 133```c 134int32_t UartSetBaud(DevHandle handle, uint32_t baudRate); 135``` 136 137**Table 3** Description of UartSetBaud 138 139| Parameter| Description| 140| -------- | -------- | 141| handle | UART device handle.| 142| baudRate | Baud rate to set.| 143| **Return Value**| **Description**| 144| HDF_SUCCESS | The operation is successful.| 145| Negative value| The operation fails.| 146 147Example: Set the UART baud rate to **9600**. 148 149```c 150int32_t ret; 151 152ret = UartSetBaud(handle, 9600); // Set the UART baud rate. 153if (ret != HDF_SUCCESS) { 154 HDF_LOGE("UartSetBaud: failed, ret %d\n", ret); 155 return ret; 156} 157``` 158 159#### Obtaining the UART Baud Rate 160 161Use **UartGetBaud()** to obtain the UART baud rate. 162 163```c 164int32_t UartGetBaud(DevHandle handle, uint32_t *baudRate); 165``` 166 167**Table 4** Description of UartGetBaud 168 169| Parameter| Description| 170| -------- | -------- | 171| handle | UART device handle.| 172| baudRate | Pointer to the UART baud rate obtained.| 173| **Return Value**| **Description**| 174| HDF_SUCCESS | The operation is successful.| 175| Negative value| The operation fails.| 176 177Example: Obtain the UART baud rate. 178 179```c 180int32_t ret; 181uint32_t baudRate; 182 183ret = UartGetBaud(handle, &baudRate); // Obtain the UART baud rate. 184if (ret != HDF_SUCCESS) { 185 HDF_LOGE("UartGetBaud: failed, ret %d\n", ret); 186 return ret; 187} 188``` 189 190#### Setting UART Device Attributes 191 192Use **UartSetAttribute()** to set UART device attributes. 193 194```c 195int32_t UartSetAttribute(DevHandle handle, struct UartAttribute *attribute); 196``` 197 198**Table 5** Description of UartSetAttribute 199 200| Parameter| Description| 201| -------- | -------- | 202| handle | UART device handle.| 203| attribute | Pointer to the UART device attributes to set.| 204| **Return Value**| **Description**| 205| HDF_SUCCESS | The operation is successful.| 206| Negative value| The operation fails.| 207 208Example: Set UART device attributes. 209 210```c 211int32_t ret; 212struct UartAttribute attribute; 213 214attribute.dataBits = UART_ATTR_DATABIT_7; // Transfer 7 bits each time. 215attribute.parity = UART_ATTR_PARITY_NONE; // Disable parity check for the data to transfer. 216attribute.stopBits = UART_ATTR_STOPBIT_1; // Set the stop bit to 1. 217attribute.rts = UART_ATTR_RTS_DIS; // Disable RTS. 218attribute.cts = UART_ATTR_CTS_DIS; // Disable CTS. 219attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; // Enable RX FIFO. 220attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; // Enable TX FIFO. 221 222ret = UartSetAttribute(handle, &attribute); // Set UART device attributes. 223if (ret != HDF_SUCCESS) { 224 HDF_LOGE("UartSetAttribute: failed, ret %d\n", ret); 225turn ret; 226} 227``` 228 229#### Obtaining UART Device Attributes 230 231Use **UartGetAttribute()** to obtain the UART device attributes. 232 233```c 234int32_t UartGetAttribute(DevHandle handle, struct UartAttribute *attribute); 235``` 236 237**Table 6** Description of UartGetAttribute 238 239| Parameter| Description| 240| -------- | -------- | 241| handle | UART device handle.| 242| attribute | Pointer to the UART device attributes obtained.| 243| **Return Value**| **Description**| 244| HDF_SUCCESS | The operation is successful.| 245| Negative value| The operation fails.| 246 247Example: Obtain UART device attributes. 248 249```c 250int32_t ret; 251struct UartAttribute attribute; 252 253ret = UartGetAttribute(handle, &attribute); // Obtain the attributes of the UART device. 254if (ret != HDF_SUCCESS) { 255 HDF_LOGE("UartGetAttribute: failed, ret %d\n", ret); 256 return ret; 257} 258``` 259 260#### Setting the UART Transmission Mode 261 262Use **UartSetTransMode()** to set the UART transmission mode. 263 264```c 265int32_t UartSetTransMode(DevHandle handle, enum UartTransMode mode); 266``` 267 268**Table 7** Description of UartSetTransMode 269 270| Parameter| Description| 271| -------- | -------- | 272| handle | UART device handle.| 273| mode | UART transmission mode to set.| 274| **Return Value**| **Description**| 275| HDF_SUCCESS | The operation is successful.| 276| Negative value| The operation fails.| 277 278Example: Set the UART transmission mode to **UART_MODE_RD_BLOCK**. 279 280```c 281int32_t ret; 282 283ret = UartSetTransMode(handle, UART_MODE_RD_BLOCK); // Sets the UART transmission mode. 284if (ret != HDF_SUCCESS) { 285 HDF_LOGE("UartSetTransMode: failed, ret %d\n", ret); 286 return ret; 287} 288``` 289 290#### Writing Data to a UART Device 291 292Use **UartWrite()** to write data of the specified length to a UART device. 293 294```c 295int32_t UartWrite(DevHandle handle, uint8_t *data, uint32_t size); 296``` 297 298**Table 8** Description of UartWrite 299 300| Parameter| Description| 301| -------- | -------- | 302| handle | UART device handle.| 303| data | Pointer to the data to write.| 304| size | Length of the data to write.| 305| **Return Value**| **Description**| 306| HDF_SUCCESS | The operation is successful.| 307| Negative value| The operation fails.| 308 309Example: Write data to a UART device. 310 311```c 312int32_t ret; 313uint8_t wbuff[5] = {1, 2, 3, 4, 5}; 314 315ret = UartWrite(handle, wbuff, 5); // Write data of the specified length to the UART device. 316if (ret != HDF_SUCCESS) { 317 HDF_LOGE("UartWrite: failed, ret %d\n", ret); 318 return ret; 319} 320``` 321 322#### Reading Data from a UART Device 323 324Use **UartRead()** to read data of the specified length from a UART device. 325 326```c 327int32_t UartRead(DevHandle handle, uint8_t *data, uint32_t size); 328``` 329 330**Table 9** Description of UartRead 331 332| Parameter| Description| 333| -------- | -------- | 334| handle | UART device handle.| 335| data | Pointer to the buffer for receiving the data.| 336| size | Length of the data to read.| 337| **Return Value**| **Description**| 338| Non-negative value| The operation is successful. The length of the data read is returned.| 339| Negative value| The operation fails.| 340 341Example: Read data of the specified length from a UART device. 342 343```c 344int32_t ret; 345uint8_t rbuff[5] = {0}; 346 347ret = UartRead(handle, rbuff, 5); // Read data of the specified length from the UART device. 348if (ret < 0) { 349 HDF_LOGE("UartRead: failed, ret %d\n", ret); 350 return ret; 351} 352``` 353 354> ![icon-caution.gif](../public_sys-resources/icon-caution.gif) **CAUTION**<br/> 355> Data is successfully read from the UART device if a non-negative value is returned. If **0** is returned, no valid data can be read from the UART device. A value greater than **0** indicates the length of the data read from the UART device. The data length must be less than or equal to the value of **size** and cannot exceed the maximum length of the data to read at a time specified by the UART controller in use. 356 357 358#### Closing a UART Device 359 360Use **UartClose()** to close a UART device. 361 362```c 363void UartClose(DevHandle handle); 364``` 365 366This function releases the resources requested by **UartOpen**. 367 368**Table 10** Description of UartClose 369 370| Parameter| Description| 371| -------- | -------- | 372| handle | UART device handle to close.| 373 374Example: Close a UART device. 375 376```c 377UartClose(handle); // Close a UART device to release resources. 378``` 379 380## Example 381 382The following uses the Hi3516D V300 development board as an example to describe how to manage the UART device. The procedure is as follows: 383 3841. Open a UART device based on the port number. The handle of the UART device opened is returned. 3852. Set the baud rate of the UART device. 3863. Obtain the baud rate of the UART device. 3874. Set the attributes of the UART device. 3885. Obtain the attributes of the UART device. 3896. Set the transmission mode of the UART device. 3907. Transfer data of the specified length. 3918. Receive data of the specified length. 3929. Closes the UART device. 393 394```c 395#include "hdf_log.h" 396#include "uart_if.h" 397 398void UartTestSample(void) 399{ 400 int32_t ret; 401 uint32_t port; 402 uint32_t baud; 403 DevHandle handle = NULL; 404 uint8_t wbuff[5] = { 1, 2, 3, 4, 5 }; 405 uint8_t rbuff[5] = { 0 }; 406 struct UartAttribute attribute; 407 408 attribute.dataBits = UART_ATTR_DATABIT_7; // Transfer 7 bits each time. 409 attribute.parity = UART_ATTR_PARITY_NONE; // Disable parity check. 410 attribute.stopBits = UART_ATTR_STOPBIT_1; // Set the stop bit to 1. 411 attribute.rts = UART_ATTR_RTS_DIS; // Disable RTS. 412 attribute.cts = UART_ATTR_CTS_DIS; // Disable CTS. 413 attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; // Enable RX FIFO. 414 attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; // Enable TX FIFO. 415 416 port = 1; // UART device port number. 417 418 handle = UartOpen(port); // Open a UART device. 419 if (handle == NULL) { 420 HDF_LOGE("UartOpen: open uart_%u failed!\n", port); 421 return; 422 } 423 424 ret = UartSetBaud(handle, 9600); // Set the UART baud rate to 9600. 425 if (ret != HDF_SUCCESS) { 426 HDF_LOGE("UartSetBaud: set baud failed, ret %d\n", ret); 427 goto ERR; 428 } 429 430 ret = UartGetBaud(handle, &baud); // Obtain the UART baud rate. 431 if (ret != HDF_SUCCESS) { 432 HDF_LOGE("UartGetBaud: get baud failed, ret %d\n", ret); 433 goto ERR; 434 } 435 436 ret = UartSetAttribute(handle, &attribute); // Set the attributes of the UART device. 437 if (ret != HDF_SUCCESS) { 438 HDF_LOGE("UartSetAttribute: set attribute failed, ret %d\n", ret); 439 goto ERR; 440 } 441 442 ret = UartGetAttribute(handle, &attribute); // Obtain the attributes of the UART device. 443 if (ret != HDF_SUCCESS) { 444 HDF_LOGE("UartGetAttribute: get attribute failed, ret %d\n", ret); 445 goto ERR; 446 } 447 448 ret = UartSetTransMode(handle, UART_MODE_RD_NONBLOCK); // Set the UART transmission mode to non-block mode. 449 if (ret != HDF_SUCCESS) { 450 HDF_LOGE("UartSetTransMode: set trans mode failed, ret %d\n", ret); 451 goto ERR; 452 } 453 454 ret = UartWrite(handle, wbuff, 5); // Write 5-byte data to the UART device. 455 if (ret != HDF_SUCCESS) { 456 HDF_LOGE("UartWrite: write data failed, ret %d\n", ret); 457 goto ERR; 458 } 459 460 ret = UartRead(handle, rbuff, 5); // Read 5-byte data from the UART device. 461 if (ret < 0) { 462 HDF_LOGE("UartRead: read data failed, ret %d\n", ret); 463 goto ERR; 464 } 465ERR: 466 UartClose(handle); // Close the UART device. 467 return ret; 468} 469``` 470