1. HDF驱动框架概述:鸿蒙系统南向架构、HDF设计理念、驱动模型分层结构

各位同学,咱们今天正式进入《鸿蒙南向设备与硬件适配》的第一章。说实话,我接触鸿蒙驱动开发也有几年了,从最早的 LiteOS 到现在的 OpenHarmony,HDF 框架的演进我基本都跟过。这一章咱们先把地基打牢——搞懂 HDF 是什么、它怎么来的、长什么样。

1.1 鸿蒙系统南向架构全景

先看一张整体架构图。鸿蒙系统分南北向,北向是应用层、框架层,南向就是咱们搞的——硬件驱动、内核、芯片适配。我习惯把南向理解为「让硬件跑起来的那一半」。

南向架构核心分层:

  • 应用层:用户可见的 APP,通过 API 调用系统服务
  • 系统服务层:提供图形、多媒体、通信等能力
  • HDF 驱动框架层:咱们的主战场,统一管理所有硬件驱动
  • 内核层:LiteOS / Linux 内核,提供基础 OS 能力
  • 硬件层:CPU、外设、传感器、显示、音频等物理设备

说白了,HDF 就是南向的「交通枢纽」。北向的 APP 想用摄像头?请求先到系统服务,再到 HDF,最后落到硬件。反过来,硬件中断来了,也是 HDF 先接住,再往上送。

鸿蒙系统南向架构分层 应用层(APP / UI) 系统服务层(图形/多媒体/通信) HDF 驱动框架层(核心) 内核层(LiteOS / Linux) 硬件层(CPU / 外设 / 传感器) 南向 驱动 开发 范围 HDF 是南向 驱动核心枢纽

1.2 HDF 设计理念:为什么要有它?

你想想看,没有 HDF 之前,嵌入式驱动开发是什么样?每个芯片厂商自己写一套驱动接口,应用层换个平台就得重写。我在早期做 LiteOS 项目时就吃过这个亏——换了个 Wi-Fi 模组,整个驱动栈几乎重来。

HDF 的设计理念,说白了就是三句话:

  1. 统一驱动模型:不管什么硬件,都按同一套框架写驱动。上层不用关心底层是谁家的芯片。
  2. 硬件抽象层(HAL):把硬件差异封装在 HDF 内部,对外暴露标准接口。我习惯叫它「硬件翻译官」。
  3. 即插即用:设备插入时自动加载对应驱动,不需要手动 insmod。这个在 IoT 场景下特别实用。

个人经验: 我刚开始接触 HDF 时,觉得它跟 Linux 的 platform 驱动有点像。但用久了发现,HDF 的「设备-驱动-服务」三层模型更清晰,尤其适合多设备协同的场景。比如一个智能音箱同时管理麦克风、扬声器、Wi-Fi、蓝牙,HDF 的调度机制比传统方式优雅得多。

1.3 驱动模型分层结构

HDF 驱动模型分三层,我画了张图帮你理解:

HDF 驱动模型三层结构 驱动服务层(Driver Service) 对外提供标准 API,供系统服务层调用 驱动设备层(Driver Device) 管理设备对象、设备节点、设备生命周期 驱动配置层(Driver Config) HCS 配置描述文件,定义设备属性与资源 三层协作 完成驱动 全生命周期

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 等