标签: #HarmonyOS #HDF #驱动开发 #Hi3861 #嵌入式 #南向开发


🧬 前言:为什么一定要用 HDF?

你可能会问:“直接操作寄存器或者调 GPIO 库不香吗?为什么要套这么厚一层 HDF 壳子?”

HDF 的核心价值:

  1. 解耦:驱动代码不依赖具体的 OS 内核。
  2. 统一管理:系统统一加载、管理驱动的生命周期(加载、初始化、卸载)。
  3. 安全性:在标准系统(Standard)中,HDF 驱动运行在用户态,挂了也不会导致内核崩溃。

HDF 驱动架构图 (Mermaid):

内核空间 / HDF 框架

1. HdfIoServiceBind
2. Dispatch
3. Bind/Init
4. GpioWrite

用户态应用 (APP)

HDF 框架管理器

驱动入口 (DriverEntry)

驱动实现逻辑

硬件 (GPIO LED)


📝 一、 配置文件:描述你的硬件 (HCS)

鸿蒙引入了 HCS (HDF Configuration Source),类似于 Linux 的设备树 (Device Tree)。我们需要告诉系统:有一个名为 sample_led 的设备。

找到源码中的 device_info.hcs (通常在 vendor/hisilicon/hispark_pegasus/hdf_config/ihct/ 下),添加节点:

root {
    device_info {
        match_attr = "hdf_manager";
        template host {
            hostName = "host0";
            priority = 100;
            // 定义一个名为 sample_host 的宿主
            device_sample :: device {
                device0 :: deviceNode {
                    policy = 2; // 2: 对外发布服务,应用层可见
                    priority = 100;
                    preload = 0; // 0: 按需加载 1: 随系统启动
                    permission = 0664;
                    moduleName = "HDF_SAMPLE_LED"; // ⚠️ 关键:要与C代码匹配
                    serviceName = "hdf_led_service"; // 应用层绑定的名字
                    deviceMatchAttr = "sample_led_config";
                }
            }
        }
    }
}


💻 二、 驱动实现:核心 C 代码

drivers/hdf_core/adapter/khdf/liteos_m/ (或其他驱动目录) 下新建 hdf_led_driver.c

驱动开发的核心就是填充 HdfDriverEntry 结构体。

1. 定义控制指令
#include "hdf_device_desc.h"
#include "hdf_log.h"
#include "gpio_if.h"

// LED 连接的 GPIO 管脚 (Hi3861通常是 GPIO 9)
#define LED_GPIO_PIN 9

// 命令码
enum {
    LED_WRITE_ON = 1,
    LED_WRITE_OFF,
};

2. 业务逻辑 (Dispatch)

这是应用层调用驱动的入口。

// 接收用户态发来的指令
static int32_t LedDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    if (cmdId == LED_WRITE_ON) {
        // 点亮 LED (低电平还是高电平取决于电路,假设低电平亮)
        GpioWrite(LED_GPIO_PIN, 0);
        HDF_LOGI("LED Driver: ON");
    } else if (cmdId == LED_WRITE_OFF) {
        // 熄灭 LED
        GpioWrite(LED_GPIO_PIN, 1);
        HDF_LOGI("LED Driver: OFF");
    } else {
        return HDF_FAILURE;
    }
    return HDF_SUCCESS;
}

3. 生命周期绑定 (Bind & Init)
// 1. 驱动对外提供的服务对象
static int32_t HdfLedDriverBind(struct HdfDeviceObject *deviceObject)
{
    static struct IDeviceIoService service = {
        .Dispatch = LedDriverDispatch, // 绑定分发函数
    };
    deviceObject->service = &service;
    return HDF_SUCCESS;
}

// 2. 驱动初始化 (设置 GPIO 方向)
static int32_t HdfLedDriverInit(struct HdfDeviceObject *deviceObject)
{
    GpioSetDir(LED_GPIO_PIN, GPIO_DIR_OUT);
    HDF_LOGI("Hdf Led Driver Init Success!");
    return HDF_SUCCESS;
}

// 3. 驱动卸载
static void HdfLedDriverRelease(struct HdfDeviceObject *deviceObject)
{
    HDF_LOGI("Hdf Led Driver Released");
}

4. 注册驱动

这一步将 C 代码与 HCS 配置文件关联起来。

// 定义驱动入口
struct HdfDriverEntry g_ledDriverEntry = {
    .moduleVersion = 1,
    .moduleName = "HDF_SAMPLE_LED", // ⚠️ 必须与 HCS 中的 moduleName 一致
    .Bind = HdfLedDriverBind,
    .Init = HdfLedDriverInit,
    .Release = HdfLedDriverRelease,
};

// 宏注册
HDF_INIT(g_ledDriverEntry);


🔨 三、 编译构建:GN 脚本

鸿蒙使用 GN + Ninja 进行构建。你需要修改 BUILD.gn 文件,将你的 .c 文件加入编译列表。

hdf_driver("hdf_sample_led") {
    sources = [
        "hdf_led_driver.c",
    ]
    include_dirs = [
        "//drivers/hdf_core/framework/include",
        "//drivers/hdf_core/framework/include/core",
        "//drivers/hdf_core/adapter/khdf/liteos_m",
    ]
}


🕹️ 四、 应用层调用:点灯时刻

最后,我们写一个简单的 APP 来验证驱动。

#include "hdf_io_service_if.h"

void TestLedDriver() {
    // 1. 获取驱动服务 (对应 HCS 中的 serviceName)
    struct HdfIoService *serv = HdfIoServiceBind("hdf_led_service");
    if (serv == NULL) {
        printf("Fail to bind service!\n");
        return;
    }

    // 2. 发送指令
    static struct HdfSBuf *data = NULL;
    static struct HdfSBuf *reply = NULL;

    // 亮灯
    printf("Send command: ON\n");
    serv->dispatcher->Dispatch(&serv->object, 1, data, reply);
    
    osDelay(100); // 延时

    // 灭灯
    printf("Send command: OFF\n");
    serv->dispatcher->Dispatch(&serv->object, 2, data, reply);

    // 3. 回收资源
    HdfIoServiceRecycle(serv);
}


🎯 总结

通过这个案例,我们走通了鸿蒙驱动开发的完整链路:

  1. HCS 配置:像填写简历一样描述硬件。
  2. HdfDriverEntry:像填写表格一样实现驱动生命周期。
  3. HdfIoServiceBind:像调用 API 一样在应用层控制硬件。

这比直接写裸机代码要复杂,但它带来的标准化可移植性,是迈向高级嵌入式开发的必经之路。

Next Step:
尝试给驱动增加一个“读取状态”的功能。在 LedDriverDispatch 中增加一个 cmdId,利用 GpioRead 读取当前 LED 的电平,并通过 reply 参数返回给应用层。这能让你理解 HDF 是如何做双向数据传输的。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐