> 文档中心 > 一个例子了解通过Openharmony的HDF框架实现简易驱动的流程

一个例子了解通过Openharmony的HDF框架实现简易驱动的流程


HDF是什么?

官方说明:

HDF(Hardware Driver Foundation)驱动框架,为驱动开发者提供驱动框架能力,包括驱动加载、驱动服务管理和驱动消息机制。旨在构建统一的驱动架构平台,为驱动开发者提供更精准、更高效的开发环境,力求做到一次开发,多系统部署。

以下通过一个最简易的例程来了解HDF,并且解释如何通过HDF框架来开发Openharmony平台设备(Platform Device)驱动,为系统及外设驱动提供访问接口。

一、创建内核态驱动(KHDF)示例驱动

本例在Openharmony中的V3.1 版本中,创建KHDF驱动程序。

1.1 创建KHDF项目

创建KHDF驱动程序步骤如下:

  • 添加目录: //driver/adapter/khdf/linux中创建目录newdevice

  • 添加文件: //driver/adapter/khdf/newdevice添加文件test_newdevice.c与Makefile

  • 添加配置: //vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs

  • 编译烧录:

1.2 驱动程序实现test_newdevice.c

通过HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。

// driver/adapter/khdf/newdevice/test_newdevice.c#include "hdf_device_desc.h"#include "hdf_dlist.h"#include "hdf_log.h"....struct HdfDriverEntry g_test_newdevice = {    .moduleVersion = 1,    .moduleName = "test_hdf_newdevice",// 通过此模块名匹配hcs配置文件中模块名    .Init = HdfNewdeviceInit,// 驱动自身业务初始的接口    .Bind = HdfNewdeviceBind,// 驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架    .Release = HdfNewdeviceRelease,// 驱动资源释放的接口};HDF_INIT(g_test_newdevice);// 注册到HDF框架

1.2.1 驱动入口

通过指定Bind,HdfNewdeviceBind将相关的服务接口绑定到HDF框架,通过Dispatch对用户态应用的消息进行处理。

// driver/adapter/khdf/newdevice/test_newdevice.c...int32_t HdfNewdeviceIoServiceDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply){    ...}int32_t HdfNewdeviceBind(struct HdfDeviceObject *deviceObject){    HDF_LOGD("enter %s", __func__);    static struct IDeviceIoService newdeviceService = { //.Open = HdfNewdeviceDriverOpen, .Dispatch = HdfNewdeviceIoServiceDispatch,// 驱动服务通过此函数进行分发处理 //.Release = HdfnewdeviceDriverClose,    };    deviceObject->service = &newdeviceService;}...

1.2.2 实现Dispatch方法

定义TEST_WRITE_DATA的cmdId号,对写入的数据进行打印,并返回应答数据。HdfDeviceSendEvent对应用端通过HdfDeviceRegisterEventListener方法注册的监听器HdfDevEventlistener对象均可以接受到cmdId消息。HdfDevEventlistener将会应用端进行说明。

// driver/adapter/khdf/newdevice/test_newdevice.c...#define TEST_WRITE_DATA 1234int32_t HdfNewdeviceIoServiceDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply){HDF_LOGD("enter %s: received cmd %d", __func__, cmdId);    if (cmdID == TEST_WRITE_DATA) { const char *readData = HdfSbufReadString(data); if (readData != NULL) {     HDF_LOGD("%s: read data is: %s", __func__, readData); }  if (HdfSbufWriteString(reply, "I am driver's reply string!")) {     return HdfDeviceSendEvent(client->device, cmdId, data); }    }    HDF_LOGE("%s: return fail", __func__);    return HDF_FAILURE;}...

1.2.3 硬件业务初始化与释放

HdfNewdeviceInit实现驱动自身业务初始的接口

HdfNewdeviceRelease实现驱动资源释放的接口

// driver/adapter/khdf/newdevice/test_newdevice.c...int32_t HdfNewdeviceInit(struct HdfDeviceObject *deviceObject){    HDF_LOGD("enter %s", __func__);    return 0;}void HdfNewdeviceRelease(struct HdfDeviceObject *deviceObject){    HDF_LOGD("enter %s", __func__);}...

1.3 Makefile

obj-y += test_newdevice.occflags-y += -I$(srctree)/include/hdf \ -I$(srctree)/include/hdf/osal \ -I$(srctree)/include/hdf/utils \ -I$(srctree)/drivers/hdf/framework/utils/include \ -I$(srctree)/drivers/hdf/khdf/osal/include \ -I$(srctree)/bounds_checking_function/include \ -I$(srctree)/drivers/hdf/framework/include/core \ -I$(srctree)/drivers/hdf/framework/core/common/include/host \ -I$(srctree)/drivers/framework/core/host/include

1.4 驱动配置

配置文件有两部份:

  • 驱动设备描述:指示驱动的加载信息内容。必选项

  • 驱动私有配置:配置驱动的硬件配置信息。可选项

1.4.1 驱动设备描述

HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描述,驱动的设备描述填写如下所示:

// vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs root { ...     test_newdevice :: host {     hostName = "test_newdevice";// host名称,host节点是用来存放某一类驱动的容器     device_sample :: device { // sample设备节点     device0 ::deviceNode {     policy = 2;     priority = 10;     preload = 0;     permission = 0664;     moduleName = "test_hdf_newdevice";     serviceName = "test_hdf_newdevice1";     deviceMatchAttr = "sample_config";  } } } ... }

policy字段是驱动服务发布的策略,在Openharmony驱动服务管理章节有详细介绍.

priority字段驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序

preload字段驱动按需加载字段

permission字段驱动创建设备节点权限

moduleName字段驱动名称,该字段的值必须和驱动入口结构的moduleName值一致

serviceName字段驱动对外发布服务的名称,必须唯一,在设备的/dev可以查看到该名称

deviceMatchAttr字段驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等

1.4.2 驱动私有配置

如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init传递给驱动,驱动的配置信息示例如下:

// vendor/hihope/rk3568/hdf_config/khdf/hdf.hcsroot {    ...    SampleDriverConfig { sample_version = 1; sample_bus = ""; match_attr = "sample_config";//该字段的值必须和device_info.hcs中的deviceMatchAttr值一致    }}

配置信息定义之后,需要将该配置文件添加到板级配置入口文件hdf.hcs.

1.5 编译烧录效果

  • 在根目录下执行 ./build.sh --product-name rk3568 --ccache

  • 单独编译内核:切换至out/kernel/src_tmp/linux-5.10目录下,执行./make-ohos.sh TB-RK3568X0

  • 进入开发板中的/dev目录下,可以查看到test_hdf_newdevice1设备

jcg路由器知识网