4. HDF 驱动框架入门:概念、分层与设备描述

驱动开发,说白了就是让操作系统能跟硬件“说话”。在 OpenHarmony 里,这个“翻译官”就是 HDF(Hardware Driver Foundation)。我刚开始接触 HDF 时,第一反应是——这不就是个驱动框架吗?后来深入项目才发现,它远不止这么简单。

4.1 HDF 是什么?为什么需要它?

HDF 的全称是 Hardware Driver Foundation,硬件驱动框架。它的核心目标就一个:让驱动开发变得标准化、可移植。

你想想看,没有框架的时候,每个驱动都是“野路子”——想怎么写就怎么写。换一个内核版本,驱动就得重写一遍。我在一个 IoT 项目里就吃过这个亏,设备从 Linux 移植到 OpenHarmony,驱动代码几乎全部重来,那叫一个痛苦。

HDF 解决了三个关键问题:

  • 解耦:把驱动和操作系统内核松绑,换内核不换驱动
  • 复用:同一套驱动代码,可以在不同硬件平台上跑
  • 标准化:定义统一的驱动模型,新人上手更快

核心观点:HDF 不是帮你写驱动,而是帮你组织驱动。它规定了“驱动该怎么写、怎么配、怎么加载”,剩下的业务逻辑还是你自己来。

4.2 HDF 框架分层架构

HDF 的分层设计,我个人觉得是它最精彩的部分。一共三层,各司其职:

层级 名称 职责 典型内容
上层 HAL(硬件抽象层) 向上提供统一 API,屏蔽硬件差异 接口定义、服务注册
中间层 Driver(驱动层) 实现具体硬件操作逻辑 设备初始化、读写、中断处理
底层 HDF Core(核心层) 驱动生命周期管理、消息分发 驱动加载、卸载、电源管理

这三层的关系,我画了一张图帮你理解:

HDF 驱动框架分层架构 HAL(硬件抽象层) 向上提供统一 API · 屏蔽硬件差异 · 服务注册与发现 Driver(驱动层) 设备初始化 · 读写操作 · 中断处理 · 硬件控制 HDF Core(核心层) 驱动生命周期管理 · 消息分发 · 电源管理 · 配置解析 数据流方向:上层应用 → HAL → Driver → HDF Core → 硬件

嗯,这里要注意:每一层只跟相邻层通信。HAL 不会直接调 HDF Core,Driver 也不会跳过 HAL 去对接上层。这种分层的好处是——哪层出问题,就只改哪层。

我的习惯:调试驱动时,先确认 HDF Core 层是否正常加载,再查 Driver 层的硬件操作,最后看 HAL 层的接口是否暴露正确。从下往上查,效率最高。

4.3 HDF Core 核心机制

HDF Core 是框架的“心脏”。它不直接操作硬件,但管着所有驱动的“生老病死”。

核心机制包括:

  • 驱动加载:根据设备描述文件,按需加载驱动
  • 驱动卸载:设备移除时,安全释放资源
  • 消息分发:把上层请求路由到正确的驱动实例
  • 电源管理:控制设备休眠、唤醒状态

我曾经遇到一个坑:驱动卸载时没有释放中断,导致系统休眠后无法唤醒。排查了两天才发现是 HDF Core 的卸载回调里漏了 HdfDeviceUnregisterService 调用。所以,卸载回调一定要写完整。

4.4 HDF 设备描述文件(HCS)

HCS 全称是 HDF Configuration Source,设备描述文件。它用树形结构描述硬件设备的信息。

说白了,HCS 就是驱动的“身份证”。系统启动时,HDF Core 会解析 HCS,知道有哪些设备、用什么驱动、资源怎么配。

一个典型的 HCS 文件长这样:

root {
    device_info {
        match_attr = "hdf_manager";
        template host {
            hostName = "";
            priority = 100;
            template device {
                deviceId = 0;
                policy = 2;
                priority = 100;
                preload = 0;
                permission = 0664;
            }
        }
        host0 : host {
            hostName = "gpio_host";
            priority = 50;
            device_gpio :: device {
                deviceId = 1;
                policy = 1;
                preload = 1;
                deviceMatchAttr = "gpio_config";
            }
        }
    }
}

关键字段说明:

字段 含义 取值示例
hostName 驱动宿主名称,用于分组 gpio_host, i2c_host
priority 加载优先级,越小越先加载 50, 100
policy 服务发布策略(0=不发布,1=发布,2=按需) 0, 1, 2
preload 是否预加载(0=否,1=是) 0, 1
deviceMatchAttr 匹配驱动配置的属性名 gpio_config

避坑指南:我曾经把 priority 写反了——数值越大优先级越高。实际上 HDF 里数值越小优先级越高。如果你有多个驱动依赖关系,一定要先加载依赖方,再加载被依赖方。

4.5 HCS 的编译与加载流程

HCS 文件不是直接给内核用的。它需要先编译成 HCB(二进制格式),然后由 HDF Core 解析加载。

流程如下:

  1. 编写 HCS:在 device/board/xxx 目录下创建 .hcs 文件
  2. 编译 HCS:使用 hc-gen 工具生成 .hcb 文件
  3. 打包进系统:HCB 文件随镜像烧录到设备
  4. 运行时解析:HDF Core 启动时读取 HCB,构建设备树
  5. 驱动匹配:根据设备树信息,加载对应的驱动

编译命令示例:

hc-gen -o out/config.hcb -p device/board/xxx/config.hcs

我个人习惯把 HCS 文件放在 device/board/<厂商>/<开发板>/hdf_config/ 目录下,这样结构清晰,方便维护。

4.6 小结

这一章我们聊了 HDF 的核心概念、三层架构、HCS 设备描述文件。记住几个关键点:

  • HDF 是驱动框架,不是驱动本身
  • 三层架构各司其职,HAL 管接口、Driver 管逻辑、HDF Core 管生命周期
  • HCS 是设备的“身份证”,用树形结构描述硬件信息
  • HCS 编译成 HCB 后,由 HDF Core 在运行时解析