三、驱动篇-HDF驱动介绍1
一、HDF驱动框架介绍
https://developer.huawei.com/consumer/cn/blog/topic/03651206763670022
HarmonyOS驱动框架采用C语言面向对象编程模型构建,通过平台解耦、内核解耦,来达到兼容不同内核,统一平台底座的目的,从而帮助开发者实现驱动的“一次开发,多系统部署”。
我们可以看到下面3个关键点信息:
- C语言面向对象编程
- 平台解耦
- 内核解耦
1.1 C面向对象编程
https://www.cnblogs.com/lihuidashen/p/13223429.html
1.2 平台解耦
目录 | 作用 |
---|---|
device\soc\rockchip\rk3568 | rk3568 芯片的平台驱动实现代码 |
drivers\hdf_core\framework\support\platform | 与平台驱动的统一适配、抽象和管理相关的实现代码 |
drivers\hdf_core\framework\include\platform | 抽象出来的接口声明,供驱动框架中的其他驱动模块使用 |
1.3 内核解耦
OpenHarmony驱动框架引入了OSAL(Operating system Abstraction Layer,操作系统抽象层),OSAL 只为驱动框架提供了内核部分能力的抽象接口,而隐藏了接口在不同内核中的实现细节。驱动程序完全不需要知道(也不会知道)自己运行在什么内核之上。
鸿蒙4.0
目录 | 作用 |
---|---|
drivers/hdf_core/adapter/khdf/liteos_m | OSAL 适配 LiteOS_M内核的实现细节 |
drivers/hdf_core/adapter/khdf/liteos | OSAL 适配 LiteOS_A内核的实现细节 |
drivers/adapter/khdf/linux | OSAL适配Linux内核的实现细节 |
drivers/hdf_core/interfaces/inner_api/osal | OSAL供驱动框架使用的统一抽象接口声明 |
二、HDF整体驱动框架
鸿蒙驱动架构采用分层解耦设计,每层聚焦特定职责,降低模块间依赖。整体分为以下层级(自底向上):
- Hardware(硬件层)
- 是物理设备的“载体”,分为两类:
- Board Support Chips(板级支持芯片):主板集成的基础通信接口芯片(如I2C、SPI、GPIO、SDIO),是设备与主板通信的“桥梁”。
- Peripheral Support Chips(外设支持芯片):外接功能硬件(如TP触摸、LCD屏幕、Sensor传感器、SDIO设备),提供具体业务能力。
2. Support(支撑层)
承上启下,为上层驱动和内核提供硬件适配与系统基础服务,分为两类子模块:
- Platform(平台驱动):对接Hardware的通信协议(I2C、SPI、GPIO、SDIO等),实现“硬件寄存器操作→标准化驱动接口”的转换,是硬件的“直接驱动层”。
- OSAL(操作系统抽象层):屏蔽不同内核(如Linux、鸿蒙微内核)的差异,提供通用基础服务(Mutex互斥锁、Thread线程、Mem内存、Time时间等),让上层模块“一次开发,多内核适配”。
3. Kernel(内核空间)
是驱动的“核心管理层”,负责设备建模、生命周期管理、资源调度,又细分为多个功能块:
- Model(设备模型):图中仅示例“Network”,代表特定设备的抽象模型(如网络设备、音频设备等),定义设备的通用行为规范。
- Host(设备主机管理):聚焦“单设备实例”的管理,包含:
<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Driver</font>
:驱动核心逻辑,<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">DeviceService</font>
对外提供设备能力,<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Private data</font>
存储设备私有配置;<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">hostService</font>
:设备服务的“中枢”,<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Observer</font>
监听设备状态(如插入、故障),<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Device/DeviceNode/DeviceObject</font>
是设备的“对象化封装”(<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">DeviceObject</font>
是核心,包含设备属性、操作方法;<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">DeviceNode</font>
是设备在系统中的唯一标识;<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Device</font>
是实例化载体);<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Loader</font>
:驱动加载器(加载/卸载驱动),<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Resource Manager</font>
:设备资源分配器(如IO地址、中断号)。
- Manager(全局设备管理):聚焦“多设备全局管控”,是系统级的设备调度中心,包含:
<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">DeviceManageService</font>
:设备管理服务“大管家”,统筹所有设备的生命周期;<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Device Host Client</font>
:与<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Host</font>
模块通信的客户端(跨模块交互),<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">DeviceTokenClnt</font>
:设备令牌客户端(处理权限/安全);<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Launcher</font>
:设备服务启动器,<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Attribute Manager</font>
:设备属性管理器;- 辅助管理模块:
<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">DeviceServiceManage</font>
(设备服务管理)、<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Fault Recovery</font>
(故障恢复)、<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Security Manager</font>
(安全策略)、<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Power Manager</font>
(电源功耗)、<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">PNP Manager</font>
(即插即用,处理热插拔)。
- VFS(虚拟文件系统):内核的“文件系统抽象层”,让所有设备能以文件/节点的形式被访问(如
<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">/dev</font>
或<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">/sys</font>
下的设备节点),是用户空间与内核驱动交互的“通用入口”。
4. Userspace(用户空间)
是应用/服务与内核驱动交互的“接口层”,包含:
<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">HDI(Hardware Driver Interface)</font>
:硬件驱动接口规范,定义用户空间与内核驱动的通信协议(如数据格式、调用流程),实现“用户态→内核态”的解耦。<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">IO-Dispatcher</font>
:IO请求调度器,管理用户空间发起的IO操作(如读写设备),负责请求的排队、分发、结果回调。
5. Tool(工具链)
辅助开发者高效实现驱动,包含:
<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">HDI-GEN</font>
:HDI代码生成工具,根据接口定义自动生成“用户态-内核态”的通信框架代码,减少重复开发。<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">Driver Module Template</font>
:驱动模块模板,提供标准化的驱动工程结构(如初始化、销毁、IO处理函数),降低入门门槛。<font style="color:rgba(0, 0, 0, 0.88);background-color:rgba(175, 184, 193, 0.2);">HCS-GEN</font>
:HCS(Hardware Configuration System,硬件配置系统)代码生成工具,自动将硬件配置文件(如设备地址、中断号)转为驱动可直接读取的代码,实现“配置与逻辑分离”。
三、HDF框架子系统概述
要开发驱动程序,首先要了解HDF定义的 设备驱动模型 ,如下图所示。HDF定义了一种组件化的设备驱动模型,可以为开发者提供更精细化的 设备驱动管理 ,让 设备驱动的开发和部署 更加规范。
介绍HDF框架常用的概念
(1)Host:按照HDF的要求,一般将类型相同、功能相似或业务关联紧密的多种设备放到一个 Host(设备集合) 里面。Host 本身有两种属性,如下表所示:
属性 | 取值 | 描述 |
---|---|---|
hostName | 字符串 | 表示宿主的名字。在不同的宿主内需要配置不同的宿主名字,在驱动框的代码中可以通过GetHostNode(const char *inHostName) 来获取匹配指定宿主名字的宿主节点。 |
priority | 整数,0~200(默认为100) | 设备集合的优先级。数值越大,优先级越低;如果优先级相同,则不能保证加载顺序。在驱动框架启动宿主时,会通过HdfAttributeManagerGetHostList() 获取到一个按priority 的值由高到低排序的宿主链表( hostList ),据此链表依次启动宿主。 |
(2)Device(设备):本身没有属性,表示具体某一小类的设备节点的集合,比如 UART 类的 device_uart 作为一个小类别,在其下会有若干个基本类似的具体的 deviceNode ,但每个 deviceNode 可能有不同的驱动服务和私有配置信息,以实现差异化的功能。
(3)Device Node(设备节点):每一个Device Node(设备节点)都有对应(多对一、一对一)的Driver(驱动程序)。HDF驱动框架给设备节点定义的属性如下表所示:
属性 | 取值 | 描述 |
---|---|---|
moduleName | 字符串 | 表示驱动的名称。它必须和驱动入口结构 struct HdfDriverEntry 中的 moduleName 的配置一致,这是驱动框架通过设备配置信息(即当前deviceNode 的配置信息)找到匹配的设备驱动程序入口的凭证。 |
preload | 整数 | 具体定义在:drivers/hdf_core/interfaces/inner_api/host/shared/hdf_device_ desc.h中 驱动被HDF加载的方式。 0:系统会在驱动框架的启动过程中默认加载当前deviceNode 的设备驱动程序 1:系统支持快速启动功能时,则会在系统完成驱动框架的启动之后再加载 preload 配置为1的deviceNode 的设备驱动程序,如果系统不支持快速启动功能,则其含义与 preload 配置为 0 的含义相同 2:系统在驱动框架的启动过程中默认不加载当前 deviceNode 的设备驱动程序,而是在用户态程序尝试绑定该驱动服务时,如果发现设备驱动服务节点不存在,驱动框架就会尝试动态加载该设备驱动 |
priority | 整数,0~200 | 驱动的优先级。数值越大,优先级越低;如果优先级相同,则不能保证加载顺序。 |
serviceName | 字符串 | 表示驱动对外发布服务的名字,该服务名字必须全局唯一,上层应用通过该名字可以找到并绑定设备驱动提供的服务。 |
policy | 整数 | 驱动对外发布服务的策略。 |
permission | 整数 | 表示驱动创建的设备服务节点的权限。该字段仅在驱动服务对用户态发布服务时(即 po1icy为 2)才有效,其值使用 UNIX 文件权限的八进制数字模式来表示,长度为4位,例如0644。开发者应当保证驱动服务的发布策略与设备服务节点的权限相互匹配,否则可能会导致无法访问驱动服务或设备服务节点的权限被放大 |
deviceMatchAttr | 字符串 | 用于匹配当前 deviceNode 的私有配置信息的关键字。如果当前 deviceNode 没有私有配置信息,则这个字段不需要填写;反之,则该字段必须和驱动私有配置信息的对应节点的 match_attr 字段的值匹配。这是当前deviceNode 的驱动程序找到对应的私有配置信息的凭证。 |
OpenHarmony 驱动框架以hcs(HDF Configuration Source,HCS)文件的形式组织源代码,以键值(Key-Value)对的形式对设备驱动信息进行配置和记录,从而实现驱动配置信息与驱动实现代码的解耦。hcs文件的源代码被hc-gen(HDF Configuration Generator,HC-GEN)工具编译成hcb(HDF Configuration Binary,HCB)二进制文件然后打包成 .o 文件链接进内核镜像中,然后在驱动框架启动阶段被 hcs-parser 工具加载和分析,还原成以g_hcsTreeRoot 为根节点的树状结构,最终被驱动框架各模块所使用。
所有的hcs文件可以简单地分成3类:
-
编译入口文件 hdf.hcs;
-
设备节点描述文件 device_info.hcs;
-
驱动私有的配置信息描述文件xxx_config.hcs。
1 hdf.hcs
在编译脚本Makefile中指定的编译hcs源文件的入口一般名为 hdf.hcs,
2 device_info.hcs - 驱动设备描述(必选)
作用:负责描述设备的整体结构和驱动的基本信息,用来描述设备结构、驱动服务。节点等元信息
描述:名为 device_info.hcs 的文件是专门用来描述设备节点的。在同一个系统中,可以有多个device_info.hcs 文件,它们的结构都一样,hc-gen 工具在编译时会把相同层级的设备节点描述文件归类合并在一起。在 device_info.hcs 文件的 root 节点下是 device_info 子节点。
例如
root {platform {rk3568_sample_config {match_attr = "rk3568_sample_config"; //该字段的值必须和device_info.hcs中的deviceMatchAttr值一致}}
}