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 19e41f4b71Sopenharmony_ci 20e41f4b71Sopenharmony_ci**Figure 2** Four-wire UART communication 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ci  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 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 >  **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