1. HDF驱动框架概述:鸿蒙系统南向架构、HDF设计理念、驱动模型分层结构
各位同学,咱们今天正式进入《鸿蒙南向设备与硬件适配》的第一章。说实话,我接触鸿蒙驱动开发也有几年了,从最早的 LiteOS 到现在的 OpenHarmony,HDF 框架的演进我基本都跟过。这一章咱们先把地基打牢——搞懂 HDF 是什么、它怎么来的、长什么样。
1.1 鸿蒙系统南向架构全景
先看一张整体架构图。鸿蒙系统分南北向,北向是应用层、框架层,南向就是咱们搞的——硬件驱动、内核、芯片适配。我习惯把南向理解为「让硬件跑起来的那一半」。
南向架构核心分层:
- 应用层:用户可见的 APP,通过 API 调用系统服务
- 系统服务层:提供图形、多媒体、通信等能力
- HDF 驱动框架层:咱们的主战场,统一管理所有硬件驱动
- 内核层:LiteOS / Linux 内核,提供基础 OS 能力
- 硬件层:CPU、外设、传感器、显示、音频等物理设备
说白了,HDF 就是南向的「交通枢纽」。北向的 APP 想用摄像头?请求先到系统服务,再到 HDF,最后落到硬件。反过来,硬件中断来了,也是 HDF 先接住,再往上送。
1.2 HDF 设计理念:为什么要有它?
你想想看,没有 HDF 之前,嵌入式驱动开发是什么样?每个芯片厂商自己写一套驱动接口,应用层换个平台就得重写。我在早期做 LiteOS 项目时就吃过这个亏——换了个 Wi-Fi 模组,整个驱动栈几乎重来。
HDF 的设计理念,说白了就是三句话:
- 统一驱动模型:不管什么硬件,都按同一套框架写驱动。上层不用关心底层是谁家的芯片。
- 硬件抽象层(HAL):把硬件差异封装在 HDF 内部,对外暴露标准接口。我习惯叫它「硬件翻译官」。
- 即插即用:设备插入时自动加载对应驱动,不需要手动 insmod。这个在 IoT 场景下特别实用。
个人经验: 我刚开始接触 HDF 时,觉得它跟 Linux 的 platform 驱动有点像。但用久了发现,HDF 的「设备-驱动-服务」三层模型更清晰,尤其适合多设备协同的场景。比如一个智能音箱同时管理麦克风、扬声器、Wi-Fi、蓝牙,HDF 的调度机制比传统方式优雅得多。
1.3 驱动模型分层结构
HDF 驱动模型分三层,我画了张图帮你理解:
1.3.1 驱动服务层
这一层是驱动对外的「门面」。系统服务层通过它来操作硬件。比如你想读取温度传感器,调用的就是驱动服务层暴露的 ReadTemp() 接口。我建议你在写驱动时,先把服务层接口设计好——接口稳定了,后面两层怎么改都不怕。
1.3.2 驱动设备层
设备层负责管理硬件设备本身。包括设备注册、设备树匹配、中断处理、DMA 传输等。嗯,这里要注意:每个设备在 HDF 里都是一个 HdfDeviceObject,驱动通过它跟硬件打交道。
1.3.3 驱动配置层
这一层用 HCS(HDF Configuration Source)文件描述设备信息。比如 GPIO 引脚号、I2C 地址、时钟频率等。我曾经踩过一个坑——HCS 文件里写错了 I2C 地址,驱动死活初始化失败,查了两天才发现是配置问题。所以,配置层一定要仔细核对硬件手册。
1.4 HDF 核心概念速览
为了让你快速上手,我把 HDF 的几个核心概念整理成了一张表:
| 概念 | 说明 | 类比 |
|---|---|---|
| HdfDriverEntry | 驱动入口结构体,包含 Bind、Init、Release 三个回调 | 类似 Linux 的 module_init |
| HdfDeviceObject | 设备对象,代表一个具体的硬件设备 | 类似 Linux 的 device |
| HdfDeviceNode | 设备节点,用于设备与服务之间的绑定 | 类似 sysfs 中的设备节点 |
| HCS 配置文件 | 描述设备属性、资源、依赖关系的配置文件 | 类似设备树 DTS |
| HdfService | 驱动对外提供的服务接口 | 类似 Linux 的 file_operations |
避坑指南: 我曾经在移植一个 I2C 触摸屏驱动时,发现 HdfDriverEntry 的 Init 回调里调用了 HdfDeviceObjectRegister,但忘记检查返回值。结果设备注册失败,驱动却以为成功了,导致后续所有操作都报空指针。记住:每个回调都要做返回值检查,别偷懒。
1.5 一个简单的 HDF 驱动骨架
光说不练假把式。下面是一个最简的 HDF 驱动代码,你感受一下结构:
#include "hdf_device_desc.h"
#include "hdf_log.h"
// 驱动初始化
static int32_t MyDriverInit(struct HdfDeviceObject *device)
{
if (device == NULL) {
HDF_LOGE("MyDriverInit: device is NULL");
return HDF_ERR_INVALID_PARAM;
}
HDF_LOGI("MyDriverInit: success");
return HDF_SUCCESS;
}
// 驱动绑定
static int32_t MyDriverBind(struct HdfDeviceObject *device)
{
if (device == NULL) {
return HDF_ERR_INVALID_PARAM;
}
// 这里可以注册服务接口
return HDF_SUCCESS;
}
// 驱动释放
static void MyDriverRelease(struct HdfDeviceObject *device)
{
if (device != NULL) {
// 清理资源
}
HDF_LOGI("MyDriverRelease: done");
}
// 驱动入口
struct HdfDriverEntry g_myDriverEntry = {
.moduleVersion = 1,
.moduleName = "my_driver",
.Bind = MyDriverBind,
.Init = MyDriverInit,
.Release = MyDriverRelease,
};
HDF_INIT(g_myDriverEntry);
你看,结构很清晰:Bind 做绑定、Init 做初始化、Release 做清理。HDF_INIT 宏把驱动注册到框架里。这个骨架你以后写任何 HDF 驱动都能复用。
1.6 本章小结
这一章咱们把 HDF 的来龙去脉理了一遍:
- 鸿蒙南向架构分五层,HDF 是驱动核心层
- HDF 设计理念是统一、抽象、即插即用
- 驱动模型分三层:服务层、设备层、配置层
- 核心概念包括 HdfDriverEntry、HdfDeviceObject、HCS 等