• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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