# UART ## 概述 ### 功能简介 UARTæŒ‡å¼‚æ¥æ”¶å‘ä¼ è¾“å™¨ï¼ˆUniversal Asynchronous Receiver/Transmitterï¼‰ï¼Œæ˜¯é€šç”¨ä¸²è¡Œæ•°æ®æ€»çº¿ï¼Œç”¨äºŽå¼‚æ¥é€šä¿¡ã€‚该总线åŒå‘通信,å¯ä»¥å®žçް免åŒå·¥ä¼ 输。 两个UART设备的连接示æ„图如下,UART与其他模å—一般用2线(图1)或4线(图2)相连,它们分别是: - TX:å‘逿•°æ®ç«¯ï¼Œå’Œå¯¹ç«¯çš„RX相连。 - RX:接收数æ®ç«¯ï¼Œå’Œå¯¹ç«¯çš„TX相连。 - RTS:å‘é€è¯·æ±‚ä¿¡å·ï¼Œç”¨äºŽæŒ‡ç¤ºæœ¬è®¾å¤‡æ˜¯å¦å‡†å¤‡å¥½ï¼Œå¯æŽ¥å—æ•°æ®ï¼Œå’Œå¯¹ç«¯CTS相连。 - CTS:å…许å‘é€ä¿¡å·ï¼Œç”¨äºŽåˆ¤æ–是å¦å¯ä»¥å‘对端å‘逿•°æ®ï¼Œå’Œå¯¹ç«¯RTS相连。 **图 1** 2线UART设备连接示æ„图  **图 2** 4线UART设备连接示æ„图  UART通信之å‰ï¼Œæ”¶å‘åŒæ–¹éœ€è¦çº¦å®šå¥½ä¸€äº›å‚æ•°ï¼šæ³¢ç‰¹çŽ‡ã€æ•°æ®æ ¼å¼ï¼ˆèµ·å§‹ä½ã€æ•°æ®ä½ã€æ ¡éªŒä½ã€åœæ¢ä½ï¼‰ç‰ã€‚通信过程ä¸ï¼ŒUART通过TXå‘é€ç»™å¯¹ç«¯æ•°æ®ï¼Œé€šè¿‡RX接收对端å‘é€çš„æ•°æ®ã€‚当UART接收缓å˜è¾¾åˆ°é¢„定的门é™å€¼æ—¶ï¼ŒRTSå˜ä¸ºä¸å¯å‘逿•°æ®ï¼Œå¯¹ç«¯çš„CTS检测到ä¸å¯å‘逿•°æ®ï¼Œåˆ™åœæ¢å‘逿•°æ®ã€‚ ### 基本概念 - 异æ¥é€šä¿¡ 异æ¥é€šä¿¡ä¸ï¼Œæ•°æ®é€šå¸¸ä»¥å—符或者å—节为å•ä½ç»„æˆå—ç¬¦å¸§ä¼ é€ã€‚å—符帧由å‘é€ç«¯é€å¸§å‘é€ï¼Œé€šè¿‡ä¼ 输线被接收设备é€å¸§æŽ¥æ”¶ã€‚å‘é€ç«¯å’ŒæŽ¥æ”¶ç«¯å¯ä»¥ç”±å„è‡ªçš„æ—¶é’Ÿæ¥æŽ§åˆ¶æ•°æ®çš„å‘é€å’ŒæŽ¥æ”¶ï¼Œè¿™ä¸¤ä¸ªæ—¶é’Ÿæºå½¼æ¤ç‹¬ç«‹ï¼Œäº’ä¸åŒæ¥ã€‚异æ¥é€šä¿¡ä»¥ä¸€ä¸ªå—ç¬¦ä¸ºä¼ è¾“å•ä½ï¼Œé€šä¿¡ä¸ä¸¤ä¸ªå—符间的时间间隔是ä¸å›ºå®šçš„,然而在åŒä¸€ä¸ªå—符ä¸çš„两个相邻ä½ä»£ç 间的时间间隔是固定的。 - å…¨åŒå·¥ä¼ 输(Full Duplex) æ¤é€šä¿¡æ¨¡å¼å…许数æ®åœ¨ä¸¤ä¸ªæ–¹å‘ä¸ŠåŒæ—¶ä¼ 输,它在能力上相当于两个å•工通信方å¼çš„结åˆã€‚å…¨åŒå·¥å¯ä»¥åŒæ—¶è¿›è¡Œä¿¡å·çš„åŒå‘ä¼ è¾“ã€‚ ### è¿ä½œæœºåˆ¶ 在HDF框架ä¸ï¼ŒUART接å£é€‚é…æ¨¡å¼é‡‡ç”¨ç‹¬ç«‹æœåŠ¡æ¨¡å¼ï¼ˆå¦‚图3æ‰€ç¤ºï¼‰ã€‚åœ¨è¿™ç§æ¨¡å¼ä¸‹ï¼Œæ¯ä¸€ä¸ªè®¾å¤‡å¯¹è±¡ä¼šç‹¬ç«‹å‘布一个设备æœåŠ¡æ¥å¤„ç†å¤–部访问,设备管ç†å™¨æ”¶åˆ°API的访问请求之åŽï¼Œé€šè¿‡æå–è¯¥è¯·æ±‚çš„å‚æ•°ï¼Œè¾¾åˆ°è°ƒç”¨å®žé™…设备对象的相应内部方法的目的。独立æœåŠ¡æ¨¡å¼å¯ä»¥ç›´æŽ¥å€ŸåŠ©HDF设备管ç†å™¨çš„æœåŠ¡ç®¡ç†èƒ½åŠ›ï¼Œä½†éœ€è¦ä¸ºæ¯ä¸ªè®¾å¤‡å•独é…ç½®è®¾å¤‡èŠ‚ç‚¹ï¼Œå¢žåŠ å†…å˜å 用。 独立æœåŠ¡æ¨¡å¼ä¸‹ï¼Œæ ¸å¿ƒå±‚ä¸ä¼šç»Ÿä¸€å‘布一个æœåŠ¡ä¾›ä¸Šå±‚ä½¿ç”¨ï¼Œå› æ¤è¿™ç§æ¨¡å¼ä¸‹é©±åЍè¦ä¸ºæ¯ä¸ªæŽ§åˆ¶å™¨å‘布一个æœåŠ¡ï¼Œå…·ä½“è¡¨çŽ°ä¸ºï¼š - 驱动适é…者需è¦å®žçްHdfDriverEntryçš„Bindé’©å函数以绑定æœåŠ¡ã€‚ - device_info.hcs文件ä¸deviceNodeçš„policyå—æ®µä¸º1或2,ä¸èƒ½ä¸º0。 UART模å—å„分层作用: - 接å£å±‚æä¾›æ‰“å¼€UART设备ã€UARTè®¾å¤‡è¯»å–æŒ‡å®šé•¿åº¦æ•°æ®ã€UART设备写入指定长度数æ®ã€è®¾ç½®UART设备波特率ã€èŽ·å–设UART设备波特率ã€è®¾ç½®UART设备属性ã€èŽ·å–UART设备波特率ã€è®¾ç½®UARTè®¾å¤‡ä¼ è¾“æ¨¡å¼ã€å…³é—UART设备的接å£ã€‚ - æ ¸å¿ƒå±‚ä¸»è¦æä¾›UART控制器的创建ã€ç§»é™¤ä»¥åŠç®¡ç†çš„能力,通过钩å函数与适é…层交互。 - 适é…å±‚ä¸»è¦æ˜¯å°†é’©å函数的功能实例化,实现具体的功能。 **图 3** UART独立æœåŠ¡æ¨¡å¼ç»“构图  ## 开呿Œ‡å¯¼ ### åœºæ™¯ä»‹ç» UART模å—应用比较广泛,主è¦ç”¨äºŽå®žçŽ°è®¾å¤‡ä¹‹é—´çš„ä½Žé€Ÿä¸²è¡Œé€šä¿¡ï¼Œä¾‹å¦‚è¾“å‡ºæ‰“å°ä¿¡æ¯ï¼Œå½“然也å¯ä»¥å¤–接å„ç§æ¨¡å—,如GPSã€è“牙ç‰ã€‚当驱动开å‘者需è¦å°†UART设备适é…到OpenHarmony时,需è¦è¿›è¡ŒUART驱动适é…。下文将介ç»å¦‚何进行UART驱动适é…。 ### 接å£è¯´æ˜Ž 为了ä¿è¯ä¸Šå±‚在调用UARTæŽ¥å£æ—¶èƒ½å¤Ÿæ£ç¡®çš„æ“ä½œUARTæŽ§åˆ¶å™¨ï¼Œæ ¸å¿ƒå±‚åœ¨//drivers/hdf_core/framework/support/platform/include/uart/uart_core.hä¸å®šä¹‰äº†ä»¥ä¸‹é’©å函数,驱动适é…者需è¦åœ¨é€‚é…层实现这些函数的具体功能,并与钩å函数挂接,从而完æˆé€‚é…å±‚ä¸Žæ ¸å¿ƒå±‚çš„äº¤äº’ã€‚ UartHostMethod定义: ```c struct UartHostMethod { int32_t (*Init)(struct UartHost *host); int32_t (*Deinit)(struct UartHost *host); int32_t (*Read)(struct UartHost *host, uint8_t *data, uint32_t size); int32_t (*Write)(struct UartHost *host, uint8_t *data, uint32_t size); int32_t (*GetBaud)(struct UartHost *host, uint32_t *baudRate); int32_t (*SetBaud)(struct UartHost *host, uint32_t baudRate); int32_t (*GetAttribute)(struct UartHost *host, struct UartAttribute *attribute); int32_t (*SetAttribute)(struct UartHost *host, struct UartAttribute *attribute); int32_t (*SetTransMode)(struct UartHost *host, enum UartTransMode mode); int32_t (*pollEvent)(struct UartHost *host, void *filep, void *table); }; ``` **表 1** UartHostMethod结构体æˆå‘˜çš„回调函数功能说明 | 函数 | å…¥å‚ | å‡ºå‚ | 返回值 | 功能 | | -------- | -------- | -------- | -------- | -------- | | Init | hostï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚UART控制器 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | åˆå§‹åŒ–Uart设备 | | Deinit | hostï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚UART控制器 | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 去åˆå§‹åŒ–Uart设备 | | Read | hostï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚UART控制器<br>size:uint32_t类型,接收数æ®å¤§å° | data:uint8_tç±»åž‹æŒ‡é’ˆï¼ŒæŽ¥æ”¶çš„æ•°æ® | HDF_STATUSç›¸å…³çŠ¶æ€ | 接收数æ®RX | | Write | hostï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚UART控制器<br>data:uint8_tç±»åž‹æŒ‡é’ˆï¼Œä¼ å…¥æ•°æ®<br>size:uint32_t类型,å‘逿•°æ®å¤§å° | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | å‘逿•°æ®TX | | SetBaud | hostï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚UART控制器<br>baudRate:uint32_tç±»åž‹ï¼Œæ³¢ç‰¹çŽ‡ä¼ å…¥å€¼ | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 设置波特率 | | GetBaud | hostï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚UART控制器 | baudRate:uint32_tç±»åž‹æŒ‡é’ˆï¼Œä¼ å‡ºçš„æ³¢ç‰¹çŽ‡ | HDF_STATUSç›¸å…³çŠ¶æ€ | 获å–当å‰è®¾ç½®çš„æ³¢ç‰¹çއ | | GetAttribute | hostï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚UART控制器 | attributeï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œä¼ å‡ºçš„å±žæ€§å€¼ï¼ˆè§uart_if.hä¸UartAttribute定义) | HDF_STATUSç›¸å…³çŠ¶æ€ | 获å–设备uart相关属性 | | SetAttribute | hostï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚UART控制器<br>attributeï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œå±žæ€§ä¼ å…¥å€¼ | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | 设置设备UART相关属性 | | SetTransMode | hostï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚UART控制器<br>mode:枚举值(è§uart_if.hä¸UartTransModeå®šä¹‰ï¼‰ï¼Œä¼ è¾“æ¨¡å¼ | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | è®¾ç½®ä¼ è¾“æ¨¡å¼ | | PollEvent | hostï¼šç»“æž„ä½“æŒ‡é’ˆï¼Œæ ¸å¿ƒå±‚UART控制器<br>filep:void类型指针filep<br>table:void类型指针table | æ— | HDF_STATUSç›¸å…³çŠ¶æ€ | poll轮询机制 | ### 开呿¥éª¤ UART模å—适é…HDF框架包å«ä»¥ä¸‹å››ä¸ªæ¥éª¤ï¼š - å®žä¾‹åŒ–é©±åŠ¨å…¥å£ - é…置属性文件 - 实例化UART控制器对象 - 驱动调试 ### å¼€å‘实例 下方将基于Hi3516DV300开呿¿ä»¥//device/soc/hisilicon/common/platform/uart/uart_hi35xx.c驱动为示例,展示需è¦é©±åЍ适é…者æä¾›å“ªäº›å†…容æ¥å®Œæ•´å®žçŽ°è®¾å¤‡åŠŸèƒ½ã€‚ 1. å®žä¾‹åŒ–é©±åŠ¨å…¥å£ é©±åŠ¨å…¥å£å¿…须为HdfDriverEntry(在hdf_device_desc.hä¸å®šä¹‰ï¼‰ç±»åž‹çš„全局å˜é‡ï¼Œä¸”moduleNameè¦å’Œdevice_info.hcsä¸ä¿æŒä¸€è‡´ã€‚HDFæ¡†æž¶ä¼šå°†æ‰€æœ‰åŠ è½½çš„é©±åŠ¨çš„HdfDriverEntryå¯¹è±¡é¦–åœ°å€æ±‡æ€»ï¼Œå½¢æˆä¸€ä¸ªç±»ä¼¼æ•°ç»„的段地å€ç©ºé—´ï¼Œæ–¹ä¾¿ä¸Šå±‚调用。 ä¸€èˆ¬åœ¨åŠ è½½é©±åŠ¨æ—¶HDF会先调用Bind函数,å†è°ƒç”¨Initå‡½æ•°åŠ è½½è¯¥é©±åŠ¨ã€‚å½“Init调用异常时,HDF框架会调用Release释放驱动资æºå¹¶é€€å‡ºã€‚ UART驱动入å£å¼€å‘å‚考: ```c struct HdfDriverEntry g_hdfUartDevice = { .moduleVersion = 1, .moduleName = "HDF_PLATFORM_UART", // ã€å¿…è¦ä¸”与HCS文件ä¸é‡Œé¢çš„moduleName匹é…】 .Bind = HdfUartDeviceBind, // 挂接UART模å—Bind实例化 .Init = HdfUartDeviceInit, // 挂接UART模å—Init实例化 .Release = HdfUartDeviceRelease, // 挂接UART模å—Release实例化 }; HDF_INIT(g_hdfUartDevice); // 调用HDF_INITå°†é©±åŠ¨å…¥å£æ³¨å†Œåˆ°HDFæ¡†æž¶ä¸ ``` 2. é…置属性文件 完æˆé©±åЍ入壿³¨å†Œä¹‹åŽï¼Œéœ€è¦åœ¨device_info.hcsæ–‡ä»¶ä¸æ·»åŠ deviceNodeä¿¡æ¯ï¼ŒdeviceNodeä¿¡æ¯ä¸Žé©±åЍ入壿³¨å†Œç›¸å…³ã€‚本例以两个UART控制器为例,如有多个器件信æ¯ï¼Œåˆ™éœ€è¦åœ¨device_info.hcsæ–‡ä»¶å¢žåŠ å¯¹åº”çš„deviceNodeä¿¡æ¯ï¼Œä»¥åŠåœ¨uart_config.hcs文件ä¸å¢žåŠ å¯¹åº”çš„å™¨ä»¶å±žæ€§ã€‚å™¨ä»¶å±žæ€§å€¼ä¸Žæ ¸å¿ƒå±‚UartHostæˆå‘˜çš„默认值或é™åˆ¶èŒƒå›´æœ‰å¯†åˆ‡å…³ç³»ï¼Œæ¯”如UART设备端å£å·ï¼Œéœ€è¦åœ¨uart_config.hcs文件ä¸å¢žåŠ å¯¹åº”çš„å™¨ä»¶å±žæ€§ã€‚ 独立æœåŠ¡æ¨¡å¼çš„特点是device_info.hcs文件ä¸è®¾å¤‡èŠ‚ç‚¹ä»£è¡¨ç€ä¸€ä¸ªè®¾å¤‡å¯¹è±¡ï¼Œå¦‚æžœå˜åœ¨å¤šä¸ªè®¾å¤‡å¯¹è±¡ï¼Œåˆ™æŒ‰éœ€æ·»åŠ ï¼Œæ³¨æ„æœåŠ¡åä¸Žé©±åŠ¨ç§æœ‰æ•°æ®åŒ¹é…的关键å—å称必须唯一。其ä¸å„项傿•°å¦‚表2所示: **表 2** device_info.hcsèŠ‚ç‚¹å‚æ•°è¯´æ˜Ž | æˆå‘˜å | 值 | | -------- | -------- | | policy | 驱动æœåŠ¡å‘布的ç–略,UART控制器具体é…置为2ï¼Œè¡¨ç¤ºé©±åŠ¨å¯¹å†…æ ¸æ€å’Œç”¨æˆ·æ€éƒ½å‘布æœåŠ¡ | | priority | 驱动å¯åŠ¨ä¼˜å…ˆçº§ï¼ˆ0-200),值越大优先级越低。UART控制器具体é…置为40 | | permission | 驱动创建设备节点æƒé™ï¼ŒUART控制器具体é…置为0664 | | moduleName | 驱动å称,UART控制器固定为HDF_PLATFORM_UART | | serviceName | 驱动对外å‘布æœåŠ¡çš„å称,UART控制器æœåŠ¡å设置为HDF_PLATFORM_UART_X,X代表UARTæŽ§åˆ¶å™¨ç¼–å· | | deviceMatchAttr | é©±åŠ¨ç§æœ‰æ•°æ®åŒ¹é…的关键å—,UART控制器设置为hisilicon_hi35xx_uart_X ,X代表UARTæŽ§åˆ¶å™¨ç¼–å· | - device_info.hcs é…ç½®å‚考: 在//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcsæ–‡ä»¶ä¸æ·»åŠ deviceNodeæè¿°ã€‚ ```c root { device_info { match_attr = "hdf_manager"; platform :: host { hostName = "platform_host"; priority = 50; device_uart :: device { device0 :: deviceNode { policy = 1; // 驱动æœåŠ¡å‘布的ç–略,policy大于ç‰äºŽ1(用户æ€å¯è§ä¸º2ï¼Œä»…å†…æ ¸æ€å¯è§ä¸º1)。 priority = 40; // 驱动å¯åŠ¨ä¼˜å…ˆçº§ permission = 0644; // 驱动创建设备节点æƒé™ moduleName = "HDF_PLATFORM_UART"; // 驱动åç§°ï¼Œè¯¥å—æ®µçš„值必须和驱动入å£ç»“构的moduleName值一致。 serviceName = "HDF_PLATFORM_UART_0"; // 驱动对外å‘布æœåŠ¡çš„åç§°ï¼Œå¿…é¡»å”¯ä¸€ï¼Œå¿…é¡»è¦æŒ‰ç…§HDF_PLATFORM_UART_Xçš„æ ¼å¼ï¼ŒX为UART控制器编å·ã€‚ deviceMatchAttr = "hisilicon_hi35xx_uart_0"; // é©±åŠ¨ç§æœ‰æ•°æ®åŒ¹é…的关键å—ï¼Œå¿…é¡»å’Œé©±åŠ¨ç§æœ‰æ•°æ®é…置表ä¸çš„match_attr值一致。 } device1 :: deviceNode { policy = 2; permission = 0644; priority = 40; moduleName = "HDF_PLATFORM_UART"; serviceName = "HDF_PLATFORM_UART_1"; deviceMatchAttr = "hisilicon_hi35xx_uart_1"; } ...... // 如果å˜åœ¨å¤šä¸ªUART设备时ã€å¿…é¡»ã€‘æ·»åŠ èŠ‚ç‚¹ï¼Œå¦åˆ™ä¸ç”¨ } } } } ``` - uart_config.hcs é…ç½®å‚考: 在//device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/uart/uart_config.hcs文件é…置器件属性,其ä¸é…ç½®å‚æ•°å¦‚下: ```c root { platform { template uart_controller { // é…置模æ¿ï¼Œå¦‚果下é¢èŠ‚ç‚¹ä½¿ç”¨æ—¶ç»§æ‰¿è¯¥æ¨¡æ¿ï¼Œåˆ™èŠ‚ç‚¹ä¸æœªå£°æ˜Žçš„å—æ®µä¼šä½¿ç”¨è¯¥æ¨¡æ¿ä¸çš„默认值 match_attr = ""; num = 0; // ã€å¿…è¦ã€‘端å£å· baudrate = 115200; // ã€å¿…è¦ã€‘æ³¢ç‰¹çŽ‡ï¼Œæ•°å€¼å¯æŒ‰éœ€å¡«å†™ fifoRxEn = 1; // ã€å¿…è¦ã€‘使能接收FIFO fifoTxEn = 1; // ã€å¿…è¦ã€‘使能å‘é€FIFO flags = 4; // ã€å¿…è¦ã€‘æ ‡å¿—ä¿¡å· regPbase = 0x120a0000; // ã€å¿…è¦ã€‘åœ°å€æ˜ å°„éœ€è¦ interrupt = 38; // ã€å¿…è¦ã€‘䏿–å· iomemCount = 0x48; // ã€å¿…è¦ã€‘åœ°å€æ˜ å°„éœ€è¦ } controller_0x120a0000 :: uart_controller { match_attr = "hisilicon_hi35xx_uart_0"; // ã€å¿…è¦ã€‘必须和device_info.hcsä¸å¯¹åº”的设备的deviceMatchAttr值一致 } controller_0x120a1000 :: uart_controller { num = 1; baudrate = 9600; regPbase = 0x120a1000; interrupt = 39; match_attr = "hisilicon_hi35xx_uart_1"; } ...... // 如果å˜åœ¨å¤šä¸ªUART设备时ã€å¿…é¡»ã€‘æ·»åŠ èŠ‚ç‚¹ï¼Œå¦åˆ™ä¸ç”¨ } } ``` éœ€è¦æ³¨æ„的是,新增uart_config.hcsé…置文件åŽï¼Œå¿…须在产å“对应的hdf.hcs文件ä¸å°†å…¶åŒ…å«å¦‚下è¯å¥æ‰€ç¤ºï¼Œå¦åˆ™é…ç½®æ–‡ä»¶æ— æ³•ç”Ÿæ•ˆã€‚ 例如:本例ä¸uart_config.hcs所在路径为device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/uart/uart_config.hcs,则必须在产å“对应的hdf.hcs䏿·»åР如䏋è¯å¥ï¼š ```c #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/uart/uart_config.hcs" // é…置文件相对路径 ``` 3. 实例化UART控制器对象 完æˆå±žæ€§æ–‡ä»¶é…置之åŽï¼Œä¸‹ä¸€æ¥å°±æ˜¯ä»¥æ ¸å¿ƒå±‚UartHost对象的åˆå§‹åŒ–ä¸ºæ ¸å¿ƒï¼ŒåŒ…æ‹¬é©±åŠ¨é€‚é…è€…è‡ªå®šä¹‰ç»“æž„ä½“ï¼ˆä¼ é€’å‚æ•°å’Œæ•°æ®ï¼‰ï¼Œå®žä¾‹åŒ–UartHostæˆå‘˜UartHostMethod(让用户å¯ä»¥é€šè¿‡æŽ¥å£æ¥è°ƒç”¨é©±åŠ¨åº•å±‚å‡½æ•°ï¼‰ï¼Œå®žçŽ°HdfDriverEntryæˆå‘˜å‡½æ•°ï¼ˆBindã€Initã€Release)。 - 驱动适é…者自定义结构体å‚考 从驱动的角度看,驱动适é…è€…è‡ªå®šä¹‰ç»“æž„ä½“æ˜¯å‚æ•°å’Œæ•°æ®çš„载体,而且uart_config.hcs文件ä¸çš„æ•°å€¼ä¼šè¢«HDF读入并通过DeviceResourceIfaceæ¥åˆå§‹åŒ–结构体æˆå‘˜ï¼Œä¸€äº›é‡è¦æ•°å€¼ä¹Ÿä¼šä¼ é€’ç»™æ ¸å¿ƒå±‚å¯¹è±¡ï¼Œä¾‹å¦‚ç«¯å£å·ã€‚ ```c struct UartPl011Port { // 驱动适é…者自定义管脚æè¿°ç»“构体 int32_t enable; unsigned long physBase; // 物ç†åœ°å€ uint32_t irqNum; // 䏿–å· uint32_t defaultBaudrate; // 默认波特率 uint32_t flags; // æ ‡å¿—ä¿¡å·ï¼Œä¸‹é¢ä¸‰ä¸ªå®ä¸Žä¹‹ç›¸å…³ #define PL011_FLG_IRQ_REQUESTED (1 << 0) #define PL011_FLG_DMA_RX_REQUESTED (1 << 1) #define PL011_FLG_DMA_TX_REQUESTED (1 << 2) struct UartDmaTransfer *rxUdt; // DMAä¼ è¾“ç›¸å…³ struct UartDriverData *udd; }; struct UartDriverData { // æ•°æ®ä¼ 输相关的结构体 uint32_t num; // 端å£å· uint32_t baudrate; // 波特率(å¯è®¾ç½®ï¼‰ struct UartAttribute attr; // æ•°æ®ä½ã€åœæ¢ä½ç‰ä¼ 输属性相关 struct UartTransfer *rxTransfer; // 缓冲区相关,å¯ç†è§£ä¸ºFIFO结构 wait_queue_head_t wait; // æ¡ä»¶å˜é‡ç›¸å…³çš„æŽ’队ç‰å¾…ä¿¡å· int32_t count; // æ•°æ®æ•°é‡ int32_t state; // UARTæŽ§åˆ¶å™¨çŠ¶æ€ #define UART_STATE_NOT_OPENED 0 #define UART_STATE_OPENING 1 #define UART_STATE_USEABLE 2 #define UART_STATE_SUSPENDED 3 uint32_t flags; // çŠ¶æ€æ ‡å¿— #define UART_FLG_DMA_RX (1 << 0) #define UART_FLG_DMA_TX (1 << 1) #define UART_FLG_RD_BLOCK (1 << 2) RecvNotify recv; // 函数指针类型,指å‘䏲壿•°æ®æŽ¥æ”¶å‡½æ•° struct UartOps *ops; // 自定义函数指针结构体 void *private; // ç§æœ‰æ•°æ® }; // UartHostæ˜¯æ ¸å¿ƒå±‚æŽ§åˆ¶å™¨ç»“æž„ä½“ï¼Œå…¶ä¸çš„æˆå‘˜åœ¨Init函数ä¸ä¼šè¢«èµ‹å€¼ã€‚ struct UartHost { struct IDeviceIoService service; // 驱动æœåŠ¡ struct HdfDeviceObject *device; // 驱动设备对象 uint32_t num; // 端å£å· OsalAtomic atom; // 原åé‡ void *priv; // ç§æœ‰æ•°æ® struct UartHostMethod *method; // 回调函数 }; ``` - UartHostæˆå‘˜å›žè°ƒå‡½æ•°ç»“构体UartHostMethod的实例化。 ```c // uart_hi35xx.c ä¸çš„示例:钩å函数的实例化 struct UartHostMethod g_uartHostMethod = { .Init = Hi35xxInit, // åˆå§‹åŒ– .Deinit = Hi35xxDeinit, // 去åˆå§‹åŒ– .Read = Hi35xxRead, // æŽ¥æ”¶æ•°æ® .Write = Hi35xxWrite, // å‘逿•°æ® .SetBaud = Hi35xxSetBaud, // 设置波特率 .GetBaud = Hi35xxGetBaud, // èŽ·å–æ³¢ç‰¹çއ .SetAttribute = Hi35xxSetAttribute, // 设置设备属性 .GetAttribute = Hi35xxGetAttribute, // 获å–设备属性 .SetTransMode = Hi35xxSetTransMode, // è®¾ç½®ä¼ è¾“æ¨¡å¼ .pollEvent = Hi35xxPollEvent, // 轮询 }; ``` - Bind函数开å‘å‚考 å…¥å‚: HdfDeviceObject:HDF框架给æ¯ä¸€ä¸ªé©±åŠ¨åˆ›å»ºçš„è®¾å¤‡å¯¹è±¡ï¼Œç”¨æ¥ä¿å˜è®¾å¤‡ç›¸å…³çš„ç§æœ‰æ•°æ®å’ŒæœåŠ¡æŽ¥å£ã€‚ 返回值: HDF_STATUS相关状æ€ï¼ˆè¡¨3为部分展示,如需使用其他状æ€ï¼Œå¯å‚考//drivers/hdf_core/interfaces/inner_api/utils/hdf_base.hä¸HDF_STATUSä¸HDF_STATUS定义)。 **表 3** HDF_STATUS相关状æ€è¯´æ˜Ž | 状æ€(值) | 问题æè¿° | | -------- | -------- | | HDF_ERR_INVALID_OBJECT | æŽ§åˆ¶å™¨å¯¹è±¡éžæ³• | | HDF_ERR_MALLOC_FAIL | 内å˜åˆ†é…失败 | | HDF_ERR_INVALID_PARAM | 傿•°éžæ³• | | HDF_ERR_IO | I/O 错误 | | HDF_SUCCESS | åˆå§‹åŒ–æˆåŠŸ | | HDF_FAILURE | åˆå§‹åŒ–失败 | 函数说明: åˆå§‹åŒ–自定义结构体对象,åˆå§‹åŒ–UartHostæˆå‘˜ã€‚ ```c //uart_hi35xx.c static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device) { ...... return (UartHostCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS; // ã€å¿…é¡»ã€‘è°ƒç”¨æ ¸å¿ƒå±‚å‡½æ•°UartHostCreate } // uart_core.cæ ¸å¿ƒå±‚UartHostCreate函数说明 struct UartHost *UartHostCreate(struct HdfDeviceObject *device) { struct UartHost *host = NULL; // 新建UartHost ...... host = (struct UartHost *)OsalMemCalloc(sizeof(*host)); // 分é…å†…å˜ ...... host->device = device; // ã€å¿…è¦ã€‘使HdfDeviceObject与UartHostå¯ä»¥ç›¸äº’è½¬åŒ–çš„å‰æ device->service = &(host->service); // ã€å¿…è¦ã€‘使HdfDeviceObject与UartHostå¯ä»¥ç›¸äº’è½¬åŒ–çš„å‰æ host->device->service->Dispatch = UartIoDispatch; // 为serviceæˆå‘˜çš„Dispatch方法赋值 OsalAtomicSet(&host->atom, 0); // 原åé‡åˆå§‹åŒ–或者原åé‡è®¾ç½® host->priv = NULL; host->method = NULL; return host; } ``` - Init函数开å‘å‚考 å…¥å‚: HdfDeviceObject:HDF框架给æ¯ä¸€ä¸ªé©±åŠ¨åˆ›å»ºçš„è®¾å¤‡å¯¹è±¡ï¼Œç”¨æ¥ä¿å˜è®¾å¤‡ç›¸å…³çš„ç§æœ‰æ•°æ®å’ŒæœåŠ¡æŽ¥å£ã€‚ 返回值: HDF_STATUS相关状æ€ã€‚ 函数说明: åˆå§‹åŒ–自定义结构体对象,åˆå§‹åŒ–UartHostæˆå‘˜ï¼Œè°ƒç”¨æ ¸å¿ƒå±‚UartAddDev函数,完æˆUARTæŽ§åˆ¶å™¨çš„æ·»åŠ ï¼ŒæŽ¥å…¥VFS。 ```c int32_t HdfUartDeviceInit(struct HdfDeviceObject *device) { int32_t ret; struct UartHost *host = NULL; HDF_LOGI("%s: entry", __func__); ...... host = UartHostFromDevice(device); // 通过serviceæˆå‘˜åŽå¼ºåˆ¶è½¬ä¸ºUartHost,赋值是在Bindå‡½æ•°ä¸ ...... ret = Hi35xxAttach(host, device); // 完æˆUartHost对象的åˆå§‹åŒ–,è§ä¸‹ ...... host->method = &g_uartHostMethod; // UartHostMethod的实例化对象的挂载 return ret; } // 完æˆUartHost对象的åˆå§‹åŒ–。 static int32_t Hi35xxAttach(struct UartHost *host, struct HdfDeviceObject *device) { int32_t ret; struct UartDriverData *udd = NULL; // uddå’Œport对象是驱动适é…è€…è‡ªå®šä¹‰çš„ç»“æž„ä½“å¯¹è±¡ï¼Œå¯æ ¹æ®éœ€è¦å®žçŽ°ç›¸å…³åŠŸèƒ½ struct UartPl011Port *port = NULL; ...... // ã€å¿…è¦ã€‘æ¥éª¤ã€1】~ã€7】主è¦å®žçް坹udd对象的实例化赋值,然åŽèµ‹å€¼ç»™æ ¸å¿ƒå±‚UartHost对象。 udd = (struct UartDriverData *)OsalMemCalloc(sizeof(*udd)); // ã€1】 ...... port = (struct UartPl011Port *)OsalMemCalloc(sizeof(struct UartPl011Port)); // ã€2】 ...... udd->ops = Pl011GetOps(); // ã€3】设备开å¯ã€å…³é—ã€å±žæ€§è®¾ç½®ã€å‘逿“作ç‰å‡½æ•°æŒ‚载。 udd->recv = PL011UartRecvNotify; // ã€4ã€‘æ•°æ®æŽ¥æ”¶é€šçŸ¥å‡½æ•°ï¼ˆæ¡ä»¶é”机制)挂载 udd->count = 0; // ã€5】 port->udd = udd; // ã€6】使UartPl011Port与UartDriverDataå¯ä»¥ç›¸äº’è½¬åŒ–çš„å‰æ ret = UartGetConfigFromHcs(port, device->property); // å°†HdfDeviceObjectçš„å±žæ€§ä¼ é€’ç»™é©±åŠ¨é€‚é…者自定义结构体,用于相关æ“作,示例代ç è§ä¸‹ ...... udd->private = port; // ã€7】 host->priv = udd; // ã€å¿…è¦ã€‘使UartHost与UartDriverDataå¯ä»¥ç›¸äº’è½¬åŒ–çš„å‰æ host->num = udd->num; // ã€å¿…è¦ã€‘UARTè®¾å¤‡å· UartAddDev(host); // ã€å¿…è¦ã€‘æ ¸å¿ƒå±‚uart_dev.cä¸çš„函数,作用:注册一个å—符设备节点到vfsï¼Œè¿™æ ·ä»Žç”¨æˆ·æ€å¯ä»¥é€šè¿‡è¿™ä¸ªè™šæ‹Ÿæ–‡ä»¶èŠ‚ç‚¹è®¿é—®UART return HDF_SUCCESS; } static int32_t UartGetConfigFromHcs(struct UartPl011Port *port, const struct DeviceResourceNode *node) { uint32_t tmp, regPbase, iomemCount; struct UartDriverData *udd = port->udd; struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); ...... // é€šè¿‡è¯·æ±‚å‚æ•°æå–相应的值,并赋值给驱动适é…者自定义的结构体。 if (iface->GetUint32(node, "num", &udd->num, 0) != HDF_SUCCESS) { HDF_LOGE("%s: read busNum fail", __func__); return HDF_FAILURE; } ...... return 0; } ``` - Release函数开å‘å‚考 å…¥å‚: HdfDeviceObject:HDF框架给æ¯ä¸€ä¸ªé©±åŠ¨åˆ›å»ºçš„è®¾å¤‡å¯¹è±¡ï¼Œç”¨æ¥ä¿å˜è®¾å¤‡ç›¸å…³çš„ç§æœ‰æ•°æ®å’ŒæœåŠ¡æŽ¥å£ã€‚ 返回值: æ— ã€‚ 函数说明: 该函数需è¦åœ¨é©±åЍ入å£ç»“构体ä¸èµ‹å€¼ç»™Release接å£ï¼Œå½“HDF框架调用Init函数åˆå§‹åŒ–驱动失败时,å¯ä»¥è°ƒç”¨Release释放驱动资æºï¼Œè¯¥å‡½æ•°ä¸éœ€åŒ…å«é‡Šæ”¾å†…å˜å’Œåˆ é™¤æŽ§åˆ¶å™¨ç‰æ“作。 >  **说明:**<br> > 所有强制转æ¢èŽ·å–相应对象的æ“ä½œå‰ææ˜¯åœ¨Init函数ä¸å…·å¤‡å¯¹åº”赋值的æ“作。 ```c void HdfUartDeviceRelease(struct HdfDeviceObject *device) { struct UartHost *host = NULL; ... host = UartHostFromDevice(device); // 这里有HdfDeviceObject到UartHost的强制转化,通过serviceæˆå‘˜ï¼Œèµ‹å€¼è§Bind函数。 ... if (host->priv != NULL) { Hi35xxDetach(host); // 驱动适é…自定义的内å˜é‡Šæ”¾å‡½æ•°ï¼Œè§ä¸‹ã€‚ } UartHostDestroy(host); // è°ƒç”¨æ ¸å¿ƒå±‚å‡½æ•°é‡Šæ”¾host } static void Hi35xxDetach(struct UartHost *host) { struct UartDriverData *udd = NULL; struct UartPl011Port *port = NULL; ... udd = host->priv; // 这里有UartHost到UartDriverData的转化 ... UartRemoveDev(host); // VFS注销 port = udd->private; // 这里有UartDriverData到UartPl011Port的转化 if (port != NULL) { if (port->physBase != 0) { OsalIoUnmap((void *)port->physBase); // 地å€åæ˜ å°„ } OsalMemFree(port); udd->private = NULL; } OsalMemFree(udd); // 释放UartDriverData host->priv = NULL; } ``` 4. 驱动调试 ã€å¯é€‰ã€‘针对新增驱动程åºï¼Œå»ºè®®éªŒè¯é©±åŠ¨åŸºæœ¬åŠŸèƒ½ï¼Œä¾‹å¦‚æŒ‚è½½åŽçš„ä¿¡æ¯å馈,数æ®ä¼ 输的æˆåŠŸä¸Žå¦ç‰ã€‚