更多内容请访问:鸿蒙技术社区https://harmonyos.51cto.com上篇文章《小型系统驱动示例程序的编译和验证》中提到,以UART驱动示例程序为例例如,驱动程序可以分为三部分:1.设备树描述文件和驱动配置描述文件(.hcs)2.驱动程序内核空间部分的实现和编译脚本3.驱动用户空间部分的实现及编译脚本本文将详细分析基于Hi3516平台的驱动第一部分配置文件的相关要点。在项目根目录执行:find./-name*.hcs./device/hisilicon/hispark_aries/sdk_liteos/config/hdf.hcs......./device/hisilicon/hispark_aries/sdk_liteos/config/watchdog/watchdog_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/hdf.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/sdio/sdio_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/input/input_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/spi/spi_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/emmc/emmc_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/device_info/device_info.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/gpio/gpio_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/rtc/rtc_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/i2c/i2c_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/lcd/lcd_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/uart/uart_config.hcs./device/海思/hispark_taurus/sdk_liteos/config/wifi/wlan_platform.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/wifi/wlan_chip_hi3881.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/usb/usb_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/watchdog/watchdog_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/pwm/pwm_config.hcs./device/hisilicon/hispark_taurus/sdk_liteos/config/dmac/dmac_config.hcs./device/qemu/arm_virt/config/hdf.hcs......./device/qemu/arm_virt/config/cfiflash/cfi_config.hcs./vendor/huawei/hdf/sample/config/spi/spi_config.hcs。/vendor/huawei/hdf/sample/config/device_info/device_info.hcs./vendor/huawei/hdf/sample/config/gpio/gpio_config.hcs./vendor/huawei/hdf/sample/config/uart/uart_config.hcs./vendor/hisilicon/hispark_aries/config/hdf.hcs......./vendor/hisilicon/hispark_aries/config/wifi/wlan_chip_hi3881.hcs./vendor/hisilicon/hispark_taurus/config/hdf.hcs./vendor/海思/hispark_taurus/config/input/input_config.hcs./vendor/hisilicon/hispark_taurus/config/device_info/device_info.hcs./vendor/hisilicon/hispark_taurus/config/hdf_test/emmc_test_config.hcs./vendor/hisilicon/hispark_taurus/config/hdf_test/sdio_test_config.hcs./vendor/hisilicon/hispark_taurus/config/hdf_test/pwm_test_config.hcs./vendor/hisilicon/hispark_taurus/config/hdf_test/hdf_test_manager/device_info.hcs./vendor/hisilicon/hispark_taurus/config/hdf_test/hdf_test.hcs./vendor/hisilicon/hispark_taurus/config/hdf_test/gpio_test_config.hcs./vendor/hisilicon/hispark_taurus/config/hdf_test/spi_test_config.hcs./vendor/hisilicon/hispark_taurus/config/hdf_test/uart_test_config.hcs./vendor/hisilicon/hispark_taurus/config/hdf_test/i2c_test_config.hcs./vendor/hisilicon/hispark_taurus/config/hdf_test/hdf_config_test.hcs./vendor/hisilicon/hispark_taurus/config/lcd/lcd_config.hcs./vendor/hisilicon/hispark_taurus/config/sensor/sensor_config.hcs./vendor/hisilicon/hispark_taurus/config/sensor/accel/bmi160_config.hcs./vendor/hisilicon/hispark_taurus/config/sensor/accel/accel_config.hcs./vendor/hisilicon/hispark_taurus/config/wifi/wlan_platform.hcs./vendor/hisilicon/hispark_taurus/config/wifi/wlan_chip_hi3881.hcs./drivers/adapter/khdf/liteos/test/tools/hc-gen/test/unittest/02_empty_root_ei/case.hcs......./drivers/adapter/khdf/liteos/test/tools/hc-gen/test/unittest/30_include_order/base2.hcs先把不相关的hispark_aries、qemu/arm_virt、test/unittest去掉,剩下的整理成表格如下:PartA灰色部分来自//drivers/adapter/khdf/liteos/hdf_lite.mk文件中HAVE_VENDOR_CONFIG的判断决定不对其进行编译,而LOSCFG_DRIVERS_HDF_TEST决定编译入口在PartB/hdf_test/Makefile中,而不是PartB/MakefilePartB/PartC中的蓝色部分,可以由开发者配置是否编译,如果PartB/hdf_test没有编译,则编译入口为PartB/Makefile。更详细的编译路径分析见上篇文章《驱动相关模块的编译》。上表中的文件可以分为三类:[3-1]Makefile:编译hcs文件的入口。简单,下面不做详细分析。LITEOSTOPDIR=//kernel/liteos_a/HDF_DRIVER=//adapter/khdf/liteos/hdf_driver.mk[定义在//drivers/adapter/khdf/liteos/lite.mk:61][3-2]device_info.hcs:这个是整个平台所有设备信息的配置汇总。设备信息可以分布在不同路径下的几个device_info.hcs文件中,最终会被hc-gen整合。device_info.hcs包含HDF框架加载驱动所需的基本信息。基于HDF框架开发的驱动,需要在device_info.hcs文件中添加相应的设备描述。官方文档对文件结构有详细解释:root{device_info{match_attr="hdf_manager";templatehost{//host模板,继承模板的节点(如下sample_host)如果你使用模板中的默认值,那么node字段可以默认//...}sample_host::host{hostName="host0";//主机名,host节点用于存放某类驱动容器priority=100;//主机启动优先级(0-200),数值越大,优先级越低。建议默认配置100。如果优先级相同,主机的加载顺序不保证device_sample::device{//sampledevicenodedevice0::deviceNode{//sampledriverDeviceNode节点policy=1;//policy字段是驱动服务发布,在驱动服务管理章节有详细介绍priority=100;//驱动启动优先级(0-200),值越大优先级越低,建议默认配置100。如果优先级相同,则无法保证设备的加载顺序。preload=0;//驱动按需加载字段,本章末有详细介绍permission=0664;//驱动创建设备节点权限moduleName="sample_driver";//驱动名称,取值该字段的必须与驱动入口结构体的moduleName值一致serviceName="sample_service";//驱动对外服务的名称必须唯一到driver私有数据配置表中的match_attr值}}}}}这里只是自己粗浅的理解:host+hostName:host是同类型??设备驱动的容器。比如下面的platformhosts包括常见的i2c/gpio/uart/sdio等,platform::host{hostName="platform_host";.......}和peripheralhosts,包括dipsplay类,input类,网络类等://vendor/hisilicon/hispark_taurus/config/device_info/device_info.hcsLine19:platform::host{Line204:display::host{Line245:input::host{Line337:network::host{Line360:sensor::host{Line384:storage::host{Line387:media::host{device:具有相同属性的特定类型的设备,如I2Cdevice、uartdevice、deviceNode:一些特定的设备节点某类特定设备,比如挂在I2C总线上的设备0和设备1,它们有自己的驱动配置device_i2c::device{device0::deviceNode{...}device1::deviceNode{...}}device_uart::device{device0::deviceNode{...}device1::deviceNode{...}}接下来就是具体的deviceNode各个字段,以上面提到的uart驱动示例程序的deviceNode为例,见//供应商/华为/hdf/sample/config/device_info/device_info.hcsdevice5::deviceNode{policy=2;priority=10;配置权限=0660;moduleName="UART_SAMPLE";//uart_sample_driverserviceName="HDF_PLATFORM_UART_5";//uart_sample_servicedeviceMatchAttr="sample_uart_5";//串口_sample_config}policy:驱动服务发布的策略,官方文档《驱动服务管理》章节有很详细的解释priority:驱动启动优先级(0-200),值越大优先级越低:0~49board-leveldrivers,50~149设备驱动,150~200接口插件设备驱动预加载:驱动加载方式支持按需加载和顺序加载。官方文档《驱动开发》章节也有很详细的解释。permission:驱动创建设备节点的权限,默认为0666moduleName="UART_SAMPLE":驱动的名称,该字段的值必须与驱动入口结构体的moduleName值一致。本文开头“2.驱动内核空间实现及编译脚本”中内核实现部分代码中的驱动入口结构体g_sampleUartDriverEntry,参见//vendor/huawei/hdf/sample/platform/uart/src/uart_sample对于代码.c文件:structHdfDriverEntryg_sampleUartDriverEntry={.moduleVersion=1,.moduleName="UART_SAMPLE",//uart_sample_driver.Bind=SampleUartDriverBind,.Init=SampleUartDriverInit,.Release=SampleUartDriverRelease,};驱动程序发布的服务名称必须是唯一的。这是调用者找到司机服务的凭据。必须完全匹配才能找到并使用相应的驱动程序服务。本文开头“3.驱动用户空间部分的实现及编译脚本”中的实现代码:#defineUART_DEV_SERVICE_NAME_PREFIX"HDF_PLATFORM_UART_%din//vendor/huawei/hdf/sample/platform/uart/dispatch/uart_if.c"//uart_sample_servicestructDevHandle*UartOpen(uint32_tport)//samplecode,port=5{...ret=snprintf_s(serviceName,MAX_DEV_NAME_SIZE+1,MAX_DEV_NAME_SIZE,UART_DEV_SERVICE_NAME_PREFIX,port);...}deviceMatchAttr="sample_uart_5":驱动私有数据匹配的关键字,必须等于驱动私有数据配置表中的match_attr值。这是将device_info.hcs中的设备信息与下面xxx_config.hcs中的设备特定资源描述链接起来的凭据。device_info.hcs是设备树的主干和树枝,xxx_config.hcs中的节点是树叶,deviceMatchAttr是树枝和树叶之间的叶柄。[3-3]xxx_config.hcs:这是对特定设备的独占资源的单独描述。不同类型的设备必须使用不同的资源,并有自己特定的描述信息。例如//vendor/huawei/hdf/sample/config/uart/uart_config.hcs文件描述了设备节点,上面的deviceMatchAttr必须匹配这里的match_attr。uart_sample{num=5;base=0x120a0000;irqNum=38;baudrate=115200;uartClk=24000000;wlen=0x60;parity=0;stopBit=0;match_attr="sample_uart_5";//uart_sample_config}uart_sample的其他字段是该设备节点的一些资源的初始化/默认配置。这些配置通过属性指向的树结构存储在HdfDeviceObject结构中:在SampleUartDriverInit(structHdfDeviceObject*device)中,调用UtachUartDevice()调用UtachUartDevice()然后读取属性树结构,解析出相关字段和值,存入structUartDevice*uartDevice结构中,供调用:structUartResource{uint32_tnum;/*UARTportnum*/uint32_tbase;/*UARTPL011baseaddress*/uint32_tirqNum;/*UARTPL011IRQnum*/uint32_tbaudrate;/*Defaultbaudrate*/uint32_twlen;/*Defaultwordlength*/uint32_tparity;/*Defaultparity*/uint32_tstopBit;/*DefaultCintlk2s;/*DefaultCintlk2s;/*UARTclock*/unsignedlongphysBase;};structUartDevice{structIDeviceIoServiceioService;structUartResourceresource;enumUartDeviceStatestate;/*UARTState*/uint32_tuartClk;/*UARTclock*/uint32_tbaudrate;/*Baudrate*/structBufferFiforxFifo;};其他类型的设备节点特定资源有它们的自己的自定义API和相关结构来做类似的事情。关于驱动配置文件的更多细节,请仔细阅读官方文档,如驱动服务的管理、消息机制的管理、HCS的语法等。更多信息请访问:Harmonyos.51cto.com,与华为官方合作打造的鸿蒙技术社区
