1. HDF 驱动框架概述

各位好,我是老张。做嵌入式驱动开发十几年了,从裸机驱动到 Linux 内核模块,再到 OpenHarmony 的 HDF,一路踩坑无数。今天咱们聊聊 HDF 的来龙去脉。

HDF,全称 Hardware Driver Foundation。说白了,它就是 OpenHarmony 给硬件驱动开发者搭的一套框架。你想想看,一个操作系统要跑在成百上千种硬件上,驱动怎么管理、怎么加载、怎么通信,总得有个规矩。HDF 就是这套规矩。

1.1 HDF 的起源与设计理念

HDF 不是凭空冒出来的。我记得 2019 年刚接触 OpenHarmony 时,团队内部讨论过一个问题:为什么不用现成的 Linux 驱动模型?

答案其实很简单——OpenHarmony 要跑的设备太杂了。从几百 KB 内存的 IoT 传感器,到几 GB 内存的富媒体设备,Linux 那套驱动模型太重了。我个人习惯把 HDF 的设计理念总结成三个词:

  • 轻量——内核态驱动可以裁剪到极致,不依赖完整的 Linux 内核
  • 跨内核——同一套驱动代码,既能跑在 LiteOS 上,也能跑在 Linux 上
  • 解耦——驱动与硬件描述分离,改个引脚不用改代码

核心设计目标:让驱动开发者只关注硬件操作逻辑,不用操心框架细节。

我在项目中遇到过最典型的场景:一个温湿度传感器驱动,在 Linux 下要写 platform_driver、设备树匹配、probe 函数……一堆模板代码。换成 HDF,核心逻辑不到 100 行,剩下的框架帮你干了。

1.2 HDF 在 OpenHarmony 中的定位

HDF 在整个 OpenHarmony 架构里处于什么位置?我画了张图,你一看就明白。

HDF 在 OpenHarmony 架构中的定位 应用层(APP / HAP) 系统服务层(SAM / 分布式软总线) HDF 驱动框架 驱动管理 | 设备配置 | 消息通信 | 电源管理 内核抽象层(KAL) 内核层(LiteOS / Linux)

看到没?HDF 卡在系统服务层和内核抽象层之间。它不直接操作硬件,而是通过 KAL 屏蔽内核差异。你写的驱动,在 HDF 框架里跑,天然就跨内核了。

我的建议:刚开始接触 HDF 时,别急着看源码。先把这张图刻在脑子里——你写的驱动最终会挂在哪一层、跟谁通信,心里要有数。

1.3 HDF 与 Linux 驱动的核心差异

这个问题我经常被问到。很多从 Linux 转过来的兄弟,上来就问:HDF 跟 Linux 驱动有啥区别?

我直接给你列个表,一目了然。

对比维度 Linux 驱动模型 HDF 驱动框架
内核依赖 强依赖 Linux 内核 通过 KAL 适配多内核
设备描述 设备树(DTS) HCS(HDF Configuration Source)
驱动加载 module_init / probe HDF 驱动管理器统一加载
用户态驱动 不支持(需 UIO) 原生支持用户态驱动
消息通信 ioctl / sysfs HDF 消息通道(统一接口)
电源管理 runtime PM / system PM HDF 电源管理框架
热插拔 udev / mdev HDF 设备热插拔事件

嗯,这里要注意。最核心的区别其实就两点:

  1. 跨内核能力——Linux 驱动绑死了内核,HDF 可以换内核跑
  2. 用户态驱动——HDF 原生支持用户态驱动,这对调试和安全性是质变

我曾经踩过的坑:刚开始写 HDF 驱动时,我习惯性地在驱动里直接调 Linux 内核 API。结果换到 LiteOS 上编译,一堆 undefined reference。记住——永远通过 KAL 接口操作内核,别绕过去。

1.4 HDF 驱动模型的核心组件

HDF 驱动模型由几个关键组件构成。我习惯用一张图来理解它们的关系。

HDF 驱动模型核心组件 驱动管理器 驱动加载/卸载 生命周期管理 设备配置 HCS 配置解析 设备树匹配 消息通道 驱动间通信 用户态/内核态桥接 设备对象 设备实例 / 属性 / 方法 电源管理 休眠/唤醒/功耗控制 说明:驱动管理器负责加载驱动,设备配置提供硬件描述, 消息通道实现跨层通信,设备对象是驱动操作硬件的句柄。

这五个组件,你写 HDF 驱动时天天都要打交道。我个人习惯先搞懂驱动管理器和设备配置,这两个是入口。消息通道和电源管理,用到再学也不迟。

1.5 一个简单的 HDF 驱动骨架

光说不练假把式。我给你看一个最简的 HDF 驱动骨架,感受一下。

#include "hdf_device_desc.h"
#include "hdf_log.h"

// 驱动绑定
static int32_t MyDriverBind(struct HdfDeviceObject *device) {
    HDF_LOGI("MyDriver: Bind called");
    return HDF_SUCCESS;
}

// 驱动初始化
static int32_t MyDriverInit(struct HdfDeviceObject *device) {
    HDF_LOGI("MyDriver: Init called");
    // 在这里做硬件初始化
    return HDF_SUCCESS;
}

// 驱动释放
static void MyDriverRelease(struct HdfDeviceObject *device) {
    HDF_LOGI("MyDriver: Release called");
    // 在这里释放资源
}

// 驱动入口结构体
struct HdfDriverEntry g_myDriverEntry = {
    .moduleVersion = 1,
    .moduleName = "my_driver",
    .Bind = MyDriverBind,
    .Init = MyDriverInit,
    .Release = MyDriverRelease,
};

// 驱动注册宏
HDF_INIT(g_myDriverEntry);

看到没?三个回调函数:Bind、Init、Release。比 Linux 驱动的 probe/remove 简单多了。你只需要关心硬件操作,框架帮你管生命周期。

我的习惯:写 HDF 驱动时,我一般先在 Init 里做硬件复位和寄存器映射,Release 里做反操作。Bind 函数我很少动,除非要跟其他驱动建立依赖关系。

1.6 本章小结

这一章我们聊了 HDF 的起源、定位和核心差异。说白了,HDF 就是 OpenHarmony 给驱动开发者搭的脚手架——让你少写模板代码,多关注硬件逻辑。

记住三件事:

  • HDF 跨内核,别写死内核 API
  • HDF 支持用户态驱动,调试更方便
  • HDF 用 HCS 描述硬件,改配置不用改代码