1e41f4b71Sopenharmony_ci# UART
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## Overview
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci### Function
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciThe 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.
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ciA UART is connected to other modules through two wires (as shown in Figure 1) or four wires (as shown in Figure 2).
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci  - TX: UART transmitter. It is connected to the RX of the peer UART.
12e41f4b71Sopenharmony_ci  - RX: UART receiver. It is connected to the TX of the peer UART.
13e41f4b71Sopenharmony_ci  - 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.
14e41f4b71Sopenharmony_ci  - 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.
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci**Figure 1** Two-wire UART communication
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ci![image1](figures/2-wire-uart-communication.png "2-wire-uart-communication")
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci**Figure 2** Four-wire UART communication
21e41f4b71Sopenharmony_ci
22e41f4b71Sopenharmony_ci ![image2](figures/4-wire-uart-communication.png "4-wire-uart-communication")
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ciThe 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.
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci### Basic Concepts
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ci- Asynchronous communication
29e41f4b71Sopenharmony_ci
30e41f4b71Sopenharmony_ci  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. 
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ci  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.
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ci- Full-duplex transmission
35e41f4b71Sopenharmony_ci
36e41f4b71Sopenharmony_ci  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.
37e41f4b71Sopenharmony_ci
38e41f4b71Sopenharmony_ci### Working Principles
39e41f4b71Sopenharmony_ci
40e41f4b71Sopenharmony_ciIn 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.
41e41f4b71Sopenharmony_ci
42e41f4b71Sopenharmony_ciIn 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:
43e41f4b71Sopenharmony_ci
44e41f4b71Sopenharmony_ci- You need to implement the **Bind()** function in **HdfDriverEntry** to bind services.
45e41f4b71Sopenharmony_ci- The **policy** field of **deviceNode** in the **device_info.hcs** file can be **1** or **2**, but not **0**.
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ciThe UART module is divided into the following layers:
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ci- 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.
50e41f4b71Sopenharmony_ci- 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.
51e41f4b71Sopenharmony_ci- Adaptation layer: instantiates the hook functions to implement specific features.
52e41f4b71Sopenharmony_ci
53e41f4b71Sopenharmony_ci**Figure 3** Independent service mode
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_ci![image3](figures/independent-service-mode.png)
56e41f4b71Sopenharmony_ci
57e41f4b71Sopenharmony_ci## Development Guidelines
58e41f4b71Sopenharmony_ci
59e41f4b71Sopenharmony_ci### When to Use
60e41f4b71Sopenharmony_ci
61e41f4b71Sopenharmony_ciThe 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. Before using your UART devices with OpenHarmony, you need to perform UART driver adaptation.
62e41f4b71Sopenharmony_ci
63e41f4b71Sopenharmony_ci### Available APIs
64e41f4b71Sopenharmony_ci
65e41f4b71Sopenharmony_ciTo enable the upper layer to successfully operate the PWM controller by calling the UART APIs, hook functions are defined in **//drivers/hdf_core/framework/support/platform/include/uart/uart_core.h** for the core layer. You need to implement these hook functions at the adaptation layer and hook them to implement the interaction between the interface layer and the core layer.
66e41f4b71Sopenharmony_ci
67e41f4b71Sopenharmony_ci**UartHostMethod**:
68e41f4b71Sopenharmony_ci
69e41f4b71Sopenharmony_ci```c
70e41f4b71Sopenharmony_cistruct UartHostMethod {
71e41f4b71Sopenharmony_ci    int32_t (*Init)(struct UartHost *host);
72e41f4b71Sopenharmony_ci    int32_t (*Deinit)(struct UartHost *host);
73e41f4b71Sopenharmony_ci    int32_t (*Read)(struct UartHost *host, uint8_t *data, uint32_t size);
74e41f4b71Sopenharmony_ci    int32_t (*Write)(struct UartHost *host, uint8_t *data, uint32_t size);
75e41f4b71Sopenharmony_ci    int32_t (*GetBaud)(struct UartHost *host, uint32_t *baudRate);
76e41f4b71Sopenharmony_ci    int32_t (*SetBaud)(struct UartHost *host, uint32_t baudRate);
77e41f4b71Sopenharmony_ci    int32_t (*GetAttribute)(struct UartHost *host, struct UartAttribute *attribute);
78e41f4b71Sopenharmony_ci    int32_t (*SetAttribute)(struct UartHost *host, struct UartAttribute *attribute);
79e41f4b71Sopenharmony_ci    int32_t (*SetTransMode)(struct UartHost *host, enum UartTransMode mode);
80e41f4b71Sopenharmony_ci    int32_t (*pollEvent)(struct UartHost *host, void *filep, void *table);
81e41f4b71Sopenharmony_ci};
82e41f4b71Sopenharmony_ci```
83e41f4b71Sopenharmony_ci
84e41f4b71Sopenharmony_ci**Table 1** Hook functions in UartHostMethod
85e41f4b71Sopenharmony_ci
86e41f4b71Sopenharmony_ci| Function| Input Parameter| Output Parameter| Return Value| Description|
87e41f4b71Sopenharmony_ci| -------- | -------- | -------- | -------- | -------- |
88e41f4b71Sopenharmony_ci| Init | **host**: structure pointer to the UART controller at the core layer.| –| HDF_STATUS| Initializes a UART device.|
89e41f4b71Sopenharmony_ci| Deinit | **host**: structure pointer to the UART controller at the core layer.| –| HDF_STATUS| Deinitializes a UART device.|
90e41f4b71Sopenharmony_ci| Read | **host**: structure pointer to the UART controller at the core layer.<br>**size**: size of the data to read, which is of the uint32_t type.| **data**: pointer to the data read, which is of the uint8_t type. | HDF_STATUS| Reads data.|
91e41f4b71Sopenharmony_ci| Write | **host**: structure pointer to the UART controller at the core layer.<br>**data**: pointer to the data to write, which is of the uint8_t type.<br>**size**: size of the data to write, which is of the uint32_t type.| –| HDF_STATUS| Writes data.|
92e41f4b71Sopenharmony_ci| SetBaud | **host**: structure pointer to the UART controller at the core layer.<br>**baudRate**: baud rate to set, which is of the uint32_t type.| –| HDF_STATUS| Sets the baud rate.|
93e41f4b71Sopenharmony_ci| GetBaud | **host**: structure pointer to the UART controller at the core layer.| **baudRate**: pointer to the baud rate obtained, which is of the uint32_t type.| HDF_STATUS| Obtains the baud rate.|
94e41f4b71Sopenharmony_ci| GetAttribute | **host**: structure pointer to the UART controller at the core layer.| **attribute**: structure pointer to the attributes obtained. For details, see **UartAttribute** in **uart_if.h**.| HDF_STATUS| Obtains UART attributes.|
95e41f4b71Sopenharmony_ci| SetAttribute | **host**: structure pointer to the UART controller at the core layer.<br>**attribute**: structure pointer to the attributes to set.| –| HDF_STATUS| Sets UART attributes.|
96e41f4b71Sopenharmony_ci| SetTransMode | **host**: structure pointer to the UART controller at the core layer.<br>**mode**: transmission mode to set. For details, see **UartTransMode** in **uart_if.h**.| –| HDF_STATUS| Sets the UART transmission mode.|
97e41f4b71Sopenharmony_ci| PollEvent | **host**: structure pointer to the UART controller at the core layer.<br>**filep**: void pointer to a file.<br>**table**: void pointer to the poll_table.| –| HDF_STATUS| Polls for the pending events.|
98e41f4b71Sopenharmony_ci
99e41f4b71Sopenharmony_ci### How to Develop
100e41f4b71Sopenharmony_ci
101e41f4b71Sopenharmony_ciThe UART module adaptation procedure is as follows:
102e41f4b71Sopenharmony_ci
103e41f4b71Sopenharmony_ci1. Instantiate the driver entry.
104e41f4b71Sopenharmony_ci2. Configure attribute files.
105e41f4b71Sopenharmony_ci3. Instantiate the UART controller object.
106e41f4b71Sopenharmony_ci4. Debug the driver.
107e41f4b71Sopenharmony_ci
108e41f4b71Sopenharmony_ci### Example
109e41f4b71Sopenharmony_ci
110e41f4b71Sopenharmony_ciThe following uses the **//device_soc_hisilicon/common/platform/uart/uart_hi35xx.c** driver of the Hi3516D V300 development board as an example to describe the UART driver adaptation.
111e41f4b71Sopenharmony_ci
112e41f4b71Sopenharmony_ci1. Instantiate the driver entry.
113e41f4b71Sopenharmony_ci
114e41f4b71Sopenharmony_ci   The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
115e41f4b71Sopenharmony_ci   Generally, the HDF calls **Bind()** and then **Init()** to load a driver. If **Init()** fails to be called, the HDF calls **Release()** to release driver resources and exit.
116e41f4b71Sopenharmony_ci
117e41f4b71Sopenharmony_ci   UART driver entry example:
118e41f4b71Sopenharmony_ci
119e41f4b71Sopenharmony_ci   ```c
120e41f4b71Sopenharmony_ci   struct HdfDriverEntry g_hdfUartDevice = {
121e41f4b71Sopenharmony_ci       .moduleVersion = 1,
122e41f4b71Sopenharmony_ci       .moduleName = "HDF_PLATFORM_UART",   // (Mandatory) The value must be the same as that of moduleName in the .hcs file.
123e41f4b71Sopenharmony_ci       .Bind = HdfUartDeviceBind,           // See the Bind function.
124e41f4b71Sopenharmony_ci       .Init = HdfUartDeviceInit,           // See the Init function.
125e41f4b71Sopenharmony_ci       .Release = HdfUartDeviceRelease,     // See the Release function.
126e41f4b71Sopenharmony_ci   };
127e41f4b71Sopenharmony_ci   HDF_INIT(g_hdfUartDevice);               // Call HDF_INIT to register the driver entry with the HDF.
128e41f4b71Sopenharmony_ci   ```
129e41f4b71Sopenharmony_ci
130e41f4b71Sopenharmony_ci2. Configure attribute files.
131e41f4b71Sopenharmony_ci
132e41f4b71Sopenharmony_ci   Add the deviceNode information to the **device_info.hcs** file. The deviceNode information is related to the driver entry registration. The following example uses two UART controllers as an example. If there are more UART controllers, add the deviceNode information to the **device_info.hcs** file for each controller. The device attribute values configured in **uart_config.hcs** are closely related to default values or value ranges of the **UartHost** members at the core layer.
133e41f4b71Sopenharmony_ci
134e41f4b71Sopenharmony_ci   - **device_info.hcs** example:
135e41f4b71Sopenharmony_ci
136e41f4b71Sopenharmony_ci      Add the deviceNode information to the **//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
137e41f4b71Sopenharmony_ci
138e41f4b71Sopenharmony_ci      ```c
139e41f4b71Sopenharmony_ci      root {
140e41f4b71Sopenharmony_ci          device_info {
141e41f4b71Sopenharmony_ci              match_attr = "hdf_manager";
142e41f4b71Sopenharmony_ci              platform :: host {
143e41f4b71Sopenharmony_ci                  hostName = "platform_host";
144e41f4b71Sopenharmony_ci                  priority = 50;
145e41f4b71Sopenharmony_ci                  device_uart :: device {
146e41f4b71Sopenharmony_ci                      device0 :: deviceNode {
147e41f4b71Sopenharmony_ci                          policy = 1;                                 // The value 1 means to publish services only to the kernel-mode processes.
148e41f4b71Sopenharmony_ci                          priority = 40;                              // Driver startup priority.
149e41f4b71Sopenharmony_ci                          permission = 0644;                          // Permission for the device node created.
150e41f4b71Sopenharmony_ci                          moduleName = "HDF_PLATFORM_UART";           // Driver name, which must be the same as moduleName in the HdfDriverEntry structure.
151e41f4b71Sopenharmony_ci                          serviceName = "HDF_PLATFORM_UART_0";        // Unique name of the service published by the driver. The name is in the HDF_PLATFORM_UART_X format. X indicates the UART controller number.
152e41f4b71Sopenharmony_ci                          deviceMatchAttr = "hisilicon_hi35xx_uart_0";// Keyword for matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver.
153e41f4b71Sopenharmony_ci                      }
154e41f4b71Sopenharmony_ci                      device1 :: deviceNode {
155e41f4b71Sopenharmony_ci                        policy = 2;                                   // The value 2 means to publish services for both kernel- and user-mode processes.
156e41f4b71Sopenharmony_ci                        permission = 0644;
157e41f4b71Sopenharmony_ci                        priority = 40;
158e41f4b71Sopenharmony_ci                        moduleName = "HDF_PLATFORM_UART"; 
159e41f4b71Sopenharmony_ci                        serviceName = "HDF_PLATFORM_UART_1";
160e41f4b71Sopenharmony_ci                        deviceMatchAttr = "hisilicon_hi35xx_uart_1";
161e41f4b71Sopenharmony_ci                      }
162e41f4b71Sopenharmony_ci                      ...
163e41f4b71Sopenharmony_ci                  }
164e41f4b71Sopenharmony_ci              }
165e41f4b71Sopenharmony_ci          }
166e41f4b71Sopenharmony_ci      }
167e41f4b71Sopenharmony_ci      ```
168e41f4b71Sopenharmony_ci
169e41f4b71Sopenharmony_ci   - **uart_config.hcs** example
170e41f4b71Sopenharmony_ci
171e41f4b71Sopenharmony_ci      Configure the device attributes in the **//device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/uart/uart_config.hcs** file. The parameters are as follows:
172e41f4b71Sopenharmony_ci
173e41f4b71Sopenharmony_ci      ```c
174e41f4b71Sopenharmony_ci      root {
175e41f4b71Sopenharmony_ci          platform {
176e41f4b71Sopenharmony_ci              template uart_controller {                   // Template configuration. If the template is used to configure device node information, the default values in the template will be used for the fields that are not declared for the node.
177e41f4b71Sopenharmony_ci                  match_attr = "";
178e41f4b71Sopenharmony_ci                  num = 0;                                 // (Mandatory) Port number.
179e41f4b71Sopenharmony_ci                  baudrate = 115200;                       // (Mandatory) Baud rate.
180e41f4b71Sopenharmony_ci                  fifoRxEn = 1;                            // (Mandatory) Enable RX FIFO.
181e41f4b71Sopenharmony_ci                  fifoTxEn = 1;                            // (Mandatory) Enable TX FIFO.
182e41f4b71Sopenharmony_ci                  flags = 4;                               // (Mandatory) flag signal.
183e41f4b71Sopenharmony_ci                  regPbase = 0x120a0000;                   // (Mandatory) Register physical base address used for address mapping.
184e41f4b71Sopenharmony_ci                  interrupt = 38;                          // (Mandatory) Interrupt number.
185e41f4b71Sopenharmony_ci                  iomemCount = 0x48;                       // (Mandatory) Used for address mapping.
186e41f4b71Sopenharmony_ci              }
187e41f4b71Sopenharmony_ci              controller_0x120a0000 :: uart_controller {
188e41f4b71Sopenharmony_ci                  match_attr = "hisilicon_hi35xx_uart_0";  // (Mandatory) The value must be the same as that of deviceMatchAttr of the device in device_info.hcs.
189e41f4b71Sopenharmony_ci              }
190e41f4b71Sopenharmony_ci              controller_0x120a1000 :: uart_controller {
191e41f4b71Sopenharmony_ci                  num = 1;
192e41f4b71Sopenharmony_ci                  baudrate = 9600;
193e41f4b71Sopenharmony_ci                  regPbase = 0x120a1000;
194e41f4b71Sopenharmony_ci                  interrupt = 39;
195e41f4b71Sopenharmony_ci                  match_attr = "hisilicon_hi35xx_uart_1";
196e41f4b71Sopenharmony_ci              }
197e41f4b71Sopenharmony_ci              ...                                          // Add node information for more UART devices.
198e41f4b71Sopenharmony_ci          }
199e41f4b71Sopenharmony_ci      }
200e41f4b71Sopenharmony_ci      ```
201e41f4b71Sopenharmony_ci
202e41f4b71Sopenharmony_ci      After the **uart_config.hcs** file is configured, include the file in the **hdf.hcs** file. Otherwise, the configuration file cannot take effect.
203e41f4b71Sopenharmony_ci
204e41f4b71Sopenharmony_ci      ```c
205e41f4b71Sopenharmony_ci      #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/uart/uart_config.hcs" // Relative path of the file.
206e41f4b71Sopenharmony_ci      ```
207e41f4b71Sopenharmony_ci
208e41f4b71Sopenharmony_ci3. Instantiate the UART controller object.
209e41f4b71Sopenharmony_ci
210e41f4b71Sopenharmony_ci   Initialize the **UartHost** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init** and **Release**) to instantiate **UartHostMethod** in **UartHost** (so that the underlying driver functions can be called).
211e41f4b71Sopenharmony_ci
212e41f4b71Sopenharmony_ci   - Define a custom structure.
213e41f4b71Sopenharmony_ci
214e41f4b71Sopenharmony_ci      To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **uart_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the UART port number, to the object at the core layer.
215e41f4b71Sopenharmony_ci
216e41f4b71Sopenharmony_ci      ```c
217e41f4b71Sopenharmony_ci      struct UartPl011Port {                       // Pin description structure customized.
218e41f4b71Sopenharmony_ci          int32_t enable;
219e41f4b71Sopenharmony_ci          unsigned long physBase;                  // Physical base address.
220e41f4b71Sopenharmony_ci          uint32_t irqNum;                         // IRQ number.
221e41f4b71Sopenharmony_ci          uint32_t defaultBaudrate;                // Default baud rate.
222e41f4b71Sopenharmony_ci          uint32_t flags;                          // Flag signals related to the following three macros.
223e41f4b71Sopenharmony_ci      #define PL011_FLG_IRQ_REQUESTED    (1 << 0)
224e41f4b71Sopenharmony_ci      #define PL011_FLG_DMA_RX_REQUESTED (1 << 1)
225e41f4b71Sopenharmony_ci      #define PL011_FLG_DMA_TX_REQUESTED (1 << 2)
226e41f4b71Sopenharmony_ci          struct UartDmaTransfer *rxUdt;           // DMA transfer.
227e41f4b71Sopenharmony_ci          struct UartDriverData *udd;
228e41f4b71Sopenharmony_ci      };
229e41f4b71Sopenharmony_ci      struct UartDriverData {                      // Structure related to data transfer
230e41f4b71Sopenharmony_ci          uint32_t num;                            // Port number.
231e41f4b71Sopenharmony_ci          uint32_t baudrate;                       // Baud rate (configurable).
232e41f4b71Sopenharmony_ci          struct UartAttribute attr;               // Attributes, such as the data bits and stop bit of the data to transfer.
233e41f4b71Sopenharmony_ci          struct UartTransfer *rxTransfer;         // Buffer structure (FIFO structure)
234e41f4b71Sopenharmony_ci          wait_queue_head_t wait;                  // Queuing signal related to conditional variables
235e41f4b71Sopenharmony_ci          int32_t count;                           // Data count.
236e41f4b71Sopenharmony_ci          int32_t state;                           // UART controller state.
237e41f4b71Sopenharmony_ci      #define UART_STATE_NOT_OPENED 0
238e41f4b71Sopenharmony_ci      #define UART_STATE_OPENING    1
239e41f4b71Sopenharmony_ci      #define UART_STATE_USEABLE    2
240e41f4b71Sopenharmony_ci      #define UART_STATE_SUSPENDED  3
241e41f4b71Sopenharmony_ci          uint32_t flags;                          // Status flags.
242e41f4b71Sopenharmony_ci      #define UART_FLG_DMA_RX       (1 << 0)
243e41f4b71Sopenharmony_ci      #define UART_FLG_DMA_TX       (1 << 1)
244e41f4b71Sopenharmony_ci      #define UART_FLG_RD_BLOCK     (1 << 2)
245e41f4b71Sopenharmony_ci          RecvNotify recv;                         // Pointer to the function that receives serial port data.
246e41f4b71Sopenharmony_ci          struct UartOps *ops;                     // Custom function pointer structure.
247e41f4b71Sopenharmony_ci          void *private;                           // Private data.
248e41f4b71Sopenharmony_ci      };
249e41f4b71Sopenharmony_ci      
250e41f4b71Sopenharmony_ci      // UartHost is the controller structure at the core layer. The Init function assigns values to the members of UartHost.
251e41f4b71Sopenharmony_ci      struct UartHost {
252e41f4b71Sopenharmony_ci          struct IDeviceIoService service;         // Driver service.
253e41f4b71Sopenharmony_ci          struct HdfDeviceObject *device;          // Driver device object.
254e41f4b71Sopenharmony_ci          uint32_t num;                            // Port number.
255e41f4b71Sopenharmony_ci          OsalAtomic atom;                         // Atomic quantity.
256e41f4b71Sopenharmony_ci          void *priv;                              // Private data.
257e41f4b71Sopenharmony_ci          struct UartHostMethod *method;           // Callback functions.
258e41f4b71Sopenharmony_ci      };
259e41f4b71Sopenharmony_ci      ```
260e41f4b71Sopenharmony_ci
261e41f4b71Sopenharmony_ci   - Instantiate **UartHostMethod** in **UartHost**.
262e41f4b71Sopenharmony_ci
263e41f4b71Sopenharmony_ci      ```c
264e41f4b71Sopenharmony_ci      // Instantiate the hook functions in uart_hi35xx.c.
265e41f4b71Sopenharmony_ci      struct UartHostMethod g_uartHostMethod = {
266e41f4b71Sopenharmony_ci          .Init = Hi35xxInit,                     // Initialize the device.
267e41f4b71Sopenharmony_ci          .Deinit = Hi35xxDeinit,                 // Deinitialize the device.
268e41f4b71Sopenharmony_ci          .Read = Hi35xxRead,                     // Receive data.
269e41f4b71Sopenharmony_ci          .Write = Hi35xxWrite,                   // Write data.
270e41f4b71Sopenharmony_ci          .SetBaud = Hi35xxSetBaud,               // Set the baud rate.
271e41f4b71Sopenharmony_ci          .GetBaud = Hi35xxGetBaud,               // Obtain the baud rate.
272e41f4b71Sopenharmony_ci          .SetAttribute = Hi35xxSetAttribute,     // Set device attributes.
273e41f4b71Sopenharmony_ci          .GetAttribute = Hi35xxGetAttribute,     //Obtain device attributes.
274e41f4b71Sopenharmony_ci          .SetTransMode = Hi35xxSetTransMode,     // Set the transmission mode.
275e41f4b71Sopenharmony_ci          .pollEvent = Hi35xxPollEvent,           // Polling for pending events.
276e41f4b71Sopenharmony_ci      };
277e41f4b71Sopenharmony_ci      ```
278e41f4b71Sopenharmony_ci
279e41f4b71Sopenharmony_ci   - Implement the **Bind** function.
280e41f4b71Sopenharmony_ci
281e41f4b71Sopenharmony_ci      Input parameter:
282e41f4b71Sopenharmony_ci
283e41f4b71Sopenharmony_ci      **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs.
284e41f4b71Sopenharmony_ci
285e41f4b71Sopenharmony_ci      Return value:
286e41f4b71Sopenharmony_ci
287e41f4b71Sopenharmony_ci      **HDF_STATUS**<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **//drivers/hdf_core/framework/include/utils/hdf_base.h** file.
288e41f4b71Sopenharmony_ci
289e41f4b71Sopenharmony_ci      **Table 2** HDF_STATUS
290e41f4b71Sopenharmony_ci
291e41f4b71Sopenharmony_ci      | Status| Description|
292e41f4b71Sopenharmony_ci      | -------- | -------- |
293e41f4b71Sopenharmony_ci      | HDF_ERR_INVALID_OBJECT | Invalid controller object.|
294e41f4b71Sopenharmony_ci      | HDF_ERR_MALLOC_FAIL | Failed to allocate memory.|
295e41f4b71Sopenharmony_ci      | HDF_ERR_INVALID_PARAM | Invalid parameter.|
296e41f4b71Sopenharmony_ci      | HDF_ERR_IO | I/O error.|
297e41f4b71Sopenharmony_ci      | HDF_SUCCESS | Initialization successful.|
298e41f4b71Sopenharmony_ci      | HDF_FAILURE | Initialization failed.|
299e41f4b71Sopenharmony_ci
300e41f4b71Sopenharmony_ci      Function description:
301e41f4b71Sopenharmony_ci
302e41f4b71Sopenharmony_ci      Initializes the custom structure object and **UartHost**.
303e41f4b71Sopenharmony_ci
304e41f4b71Sopenharmony_ci      ```c
305e41f4b71Sopenharmony_ci      //uart_hi35xx.c
306e41f4b71Sopenharmony_ci      static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device)
307e41f4b71Sopenharmony_ci      {
308e41f4b71Sopenharmony_ci          ...
309e41f4b71Sopenharmony_ci          return (UartHostCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS; // (Mandatory) Call UartHostCreate.
310e41f4b71Sopenharmony_ci      }
311e41f4b71Sopenharmony_ci
312e41f4b71Sopenharmony_ci      // Description of UartHostCreate() in uart_core.c
313e41f4b71Sopenharmony_ci      struct UartHost *UartHostCreate(struct HdfDeviceObject *device)
314e41f4b71Sopenharmony_ci      {
315e41f4b71Sopenharmony_ci          struct UartHost *host = NULL                                         // Create UartHost.
316e41f4b71Sopenharmony_ci          ...                                                                  
317e41f4b71Sopenharmony_ci          host = (struct UartHost *)OsalMemCalloc(sizeof(*host));              // Allocate memory.
318e41f4b71Sopenharmony_ci          ...
319e41f4b71Sopenharmony_ci          host->device = device;                                               // (Mandatory) Prerequisites for conversion between HdfDeviceObject and UartHost.
320e41f4b71Sopenharmony_ci          device->service = &(host->service);                                  // (Mandatory) Prerequisites for conversion between HdfDeviceObject and UartHost.
321e41f4b71Sopenharmony_ci          host->device->service->Dispatch = UartIoDispatch;                    // Assign values to Dispatch() of service.
322e41f4b71Sopenharmony_ci          OsalAtomicSet(&host->atom, 0);                                       // Initialize or set the atomic service.
323e41f4b71Sopenharmony_ci          host->priv = NULL;
324e41f4b71Sopenharmony_ci          host->method = NULL;
325e41f4b71Sopenharmony_ci          return host;
326e41f4b71Sopenharmony_ci      }
327e41f4b71Sopenharmony_ci      ```
328e41f4b71Sopenharmony_ci
329e41f4b71Sopenharmony_ci   - Implement the **Init** function.
330e41f4b71Sopenharmony_ci
331e41f4b71Sopenharmony_ci      Input parameter:
332e41f4b71Sopenharmony_ci
333e41f4b71Sopenharmony_ci      **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs.
334e41f4b71Sopenharmony_ci
335e41f4b71Sopenharmony_ci      Return value:
336e41f4b71Sopenharmony_ci
337e41f4b71Sopenharmony_ci      HDF_STATUS
338e41f4b71Sopenharmony_ci
339e41f4b71Sopenharmony_ci      Function description:
340e41f4b71Sopenharmony_ci
341e41f4b71Sopenharmony_ci      Initialize the custom structure and **UartHost**, calls **UartAddDev()** at the core layer to add the UART controller, and accesses the VFS.
342e41f4b71Sopenharmony_ci
343e41f4b71Sopenharmony_ci      ```c
344e41f4b71Sopenharmony_ci      int32_t HdfUartDeviceInit(struct HdfDeviceObject *device)
345e41f4b71Sopenharmony_ci      {
346e41f4b71Sopenharmony_ci          int32_t ret;
347e41f4b71Sopenharmony_ci          struct UartHost *host = NULL;
348e41f4b71Sopenharmony_ci          HDF_LOGI("%s: entry", __func__);
349e41f4b71Sopenharmony_ci          ...
350e41f4b71Sopenharmony_ci          host = UartHostFromDevice(device);                                           // Forcibly convert to UartHost by using service. The values are assigned by Bind().
351e41f4b71Sopenharmony_ci          ...                                    
352e41f4b71Sopenharmony_ci          ret = Hi35xxAttach(host, device);                                            // Initialize the UartHost object.
353e41f4b71Sopenharmony_ci          ...                                    
354e41f4b71Sopenharmony_ci          host->method = &g_uartHostMethod;                                            // Attach the UartHostMethod instance.
355e41f4b71Sopenharmony_ci          return ret;
356e41f4b71Sopenharmony_ci      }
357e41f4b71Sopenharmony_ci      // Initialize UartHost.
358e41f4b71Sopenharmony_ci      static int32_t Hi35xxAttach(struct UartHost *host, struct HdfDeviceObject *device)
359e41f4b71Sopenharmony_ci      {
360e41f4b71Sopenharmony_ci          int32_t ret;
361e41f4b71Sopenharmony_ci          struct UartDriverData *udd = NULL;                                           // udd and port are custom structure objects. You can implement features as required.
362e41f4b71Sopenharmony_ci          struct UartPl011Port *port = NULL;
363e41f4b71Sopenharmony_ci          ...
364e41f4b71Sopenharmony_ci          // Steps 1 to 7 assign values to the udd object and then UartHost.
365e41f4b71Sopenharmony_ci          udd = (struct UartDriverData *)OsalMemCalloc(sizeof(*udd));                  // Step 1
366e41f4b71Sopenharmony_ci          ...
367e41f4b71Sopenharmony_ci          port = (struct UartPl011Port *)OsalMemCalloc(sizeof(struct UartPl011Port));  // Step 2
368e41f4b71Sopenharmony_ci          ...
369e41f4b71Sopenharmony_ci          udd->ops = Pl011GetOps();                                                    // Step 3 Hook the functions for opening or closing a device, setting device attributes, and sending data.
370e41f4b71Sopenharmony_ci          udd->recv = PL011UartRecvNotify;                                             // Step 4 Hook the data receiving notification function (conditional lock mechanism).
371e41f4b71Sopenharmony_ci          udd->count = 0;                                                              // Step 5.
372e41f4b71Sopenharmony_ci          port->udd = udd;                                                             // Step 6 Prerequisites for conversion between UartPl011Port and UartDriverData.
373e41f4b71Sopenharmony_ci          ret = UartGetConfigFromHcs(port, device->property);                          // Pass the attributes of HdfDeviceObject to the custom structure to perform related operations. The sample code is as follows:
374e41f4b71Sopenharmony_ci          ...
375e41f4b71Sopenharmony_ci          udd->private = port;                                                         // Step 7
376e41f4b71Sopenharmony_ci          host->priv = udd;                                                            // (Mandatory) Prerequisites for conversion between UartHost and UartDriverData.
377e41f4b71Sopenharmony_ci          host->num = udd->num;                                                        // (Mandatory) UART device number.
378e41f4b71Sopenharmony_ci          UartAddDev(host);                                                            // (Mandatory) Function in uart_dev.c at the core layer used to register a character device node to the VFS so that the UART can be accessed through the virtual file node in user mode. 
379e41f4b71Sopenharmony_ci          return HDF_SUCCESS;
380e41f4b71Sopenharmony_ci      }
381e41f4b71Sopenharmony_ci      
382e41f4b71Sopenharmony_ci      static int32_t UartGetConfigFromHcs(struct UartPl011Port *port, const struct DeviceResourceNode *node)
383e41f4b71Sopenharmony_ci      {
384e41f4b71Sopenharmony_ci          uint32_t tmp, regPbase, iomemCount;
385e41f4b71Sopenharmony_ci          struct UartDriverData *udd = port->udd;
386e41f4b71Sopenharmony_ci          struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 
387e41f4b71Sopenharmony_ci          ...
388e41f4b71Sopenharmony_ci          // Extract the values based on the request and assign the values to the custom structures.
389e41f4b71Sopenharmony_ci          if (iface->GetUint32(node, "num", &udd->num, 0) != HDF_SUCCESS) {
390e41f4b71Sopenharmony_ci              HDF_LOGE("%s: read busNum fail", __func__);
391e41f4b71Sopenharmony_ci              return HDF_FAILURE;
392e41f4b71Sopenharmony_ci          }
393e41f4b71Sopenharmony_ci          ...
394e41f4b71Sopenharmony_ci          return 0;
395e41f4b71Sopenharmony_ci          }
396e41f4b71Sopenharmony_ci      ```
397e41f4b71Sopenharmony_ci
398e41f4b71Sopenharmony_ci   - Implement the **Release** function.
399e41f4b71Sopenharmony_ci
400e41f4b71Sopenharmony_ci      Input parameter:
401e41f4b71Sopenharmony_ci
402e41f4b71Sopenharmony_ci      **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs.
403e41f4b71Sopenharmony_ci
404e41f4b71Sopenharmony_ci      Return value:
405e41f4b71Sopenharmony_ci
406e41f4b71Sopenharmony_ci      No value is returned.
407e41f4b71Sopenharmony_ci
408e41f4b71Sopenharmony_ci      Function description:
409e41f4b71Sopenharmony_ci
410e41f4b71Sopenharmony_ci      Releases the memory and deletes the controller. This function assigns values to **Release()** in the driver entry structure. When the HDF fails to call **Init()** to initialize the driver, **Release()** is called to release driver resources.
411e41f4b71Sopenharmony_ci
412e41f4b71Sopenharmony_ci      > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
413e41f4b71Sopenharmony_ci      > All forced conversion operations for obtaining the corresponding object can be successful only when **Init()** has the corresponding value assignment operations.
414e41f4b71Sopenharmony_ci
415e41f4b71Sopenharmony_ci      ```c
416e41f4b71Sopenharmony_ci      void HdfUartDeviceRelease(struct HdfDeviceObject *device)
417e41f4b71Sopenharmony_ci      {
418e41f4b71Sopenharmony_ci          struct UartHost *host = NULL;
419e41f4b71Sopenharmony_ci          ...
420e41f4b71Sopenharmony_ci          host = UartHostFromDevice(device);           // Forcible conversion from HdfDeviceObject to UartHost through the service member. For details about the value assignment, see the Bind function.
421e41f4b71Sopenharmony_ci          ...                                          
422e41f4b71Sopenharmony_ci          if (host->priv != NULL) {                    
423e41f4b71Sopenharmony_ci              Hi35xxDetach(host);                      // Customized memory release function. For details, see the following.
424e41f4b71Sopenharmony_ci          }                                            
425e41f4b71Sopenharmony_ci          UartHostDestroy(host);                       // Call the core layer function to release the host.
426e41f4b71Sopenharmony_ci      }
427e41f4b71Sopenharmony_ci      
428e41f4b71Sopenharmony_ci      static void Hi35xxDetach(struct UartHost *host)
429e41f4b71Sopenharmony_ci      {
430e41f4b71Sopenharmony_ci          struct UartDriverData *udd = NULL;
431e41f4b71Sopenharmony_ci          struct UartPl011Port *port = NULL;
432e41f4b71Sopenharmony_ci          ...
433e41f4b71Sopenharmony_ci          udd = host->priv;                            // The conversion from UartHost to UartDriverData is involved.
434e41f4b71Sopenharmony_ci          ...                                          
435e41f4b71Sopenharmony_ci          UartRemoveDev (host);                        // Remove the VFS.
436e41f4b71Sopenharmony_ci          port = udd->private;                         // The conversion from UartDriverData to UartPl011Port is involved.
437e41f4b71Sopenharmony_ci          if (port != NULL) {                          
438e41f4b71Sopenharmony_ci              if (port->physBase != 0) {               
439e41f4b71Sopenharmony_ci                  OsalIoUnmap((void *)port->physBase); // Unmap addresses.
440e41f4b71Sopenharmony_ci              }
441e41f4b71Sopenharmony_ci              OsalMemFree(port);
442e41f4b71Sopenharmony_ci              udd->private = NULL;
443e41f4b71Sopenharmony_ci          }
444e41f4b71Sopenharmony_ci          OsalMemFree (udd);                           // Release UartDriverData.
445e41f4b71Sopenharmony_ci          host->priv = NULL;
446e41f4b71Sopenharmony_ci      }
447e41f4b71Sopenharmony_ci      ```
448e41f4b71Sopenharmony_ci
449e41f4b71Sopenharmony_ci4. Debug the driver.
450e41f4b71Sopenharmony_ci
451e41f4b71Sopenharmony_ci   (Optional) For new drivers, verify basic functions, for example, check the information returned after the driver is attached and whether data is successfully transmitted.
452