OpenHarmony-简单的HDF驱动

学习于:https://docs.openharmony.cn/pages/v5.0/zh-cn/device-dev/driver/driver-hdf-manage.md

首先,OpenHarmony系统里的HDF(Hardware Driver Foundation)驱动框架,已经规范设备驱动的模型、设备节点的配置与统一的HDI(Hardware Device Interface)驱动调用接口等等。

每个设备驱动都是由一个struct HdfDriverEntry对象来描述,如:

c 复制代码
static struct HdfDriverEntry myTestEntry = {
    .moduleVersion = 1, //指定驱动源码版本
    .moduleName = "myTestDriver", //驱动模块名,.hcs文件必须有设备节点使用同名都会匹配
    .Bind = myBind, //指定驱动模块与设备节点匹配上后调用myBind函数,可绑定向应用程序提供HDI应用程序调用驱动的服务
    .Init = myInit, //匹配后,触发调用myInit函数完成初始化工作
    .Release = myRelease, //myInit初始化函数执行失败时触发调用myRelease函数释放资源
};
//通过HDF_INIT宏将结构体变量存储在系统镜像的".hdf.driver"段区,在系统启动时在取出此结构体变量进行注册至HDF框架中。
HDF_INIT(myTestEntry);

接下来通过开发一个简单的HDF驱动案例来学习,主要步骤过程:
1. HDF设备驱动的开发

这里为了省事,编写出的设备驱动源文件寄生于系统现存的驱动编译管理中。如在OpenHarmony系统源码drivers/hdf_core/adapter/khdf/liteos/platform/src/目录下创建myTestDriver.c,并在文件输入代码如下:

c 复制代码
#include "hdf_device_desc.h"          // HDF框架对驱动开发相关能力接口的头文件
#include "hdf_log.h"                  // HDF框架提供的日志接口头文件
#include "hdf_base.h"                 // HDI驱动调用接口头文件

int32_t myBind(struct HdfDeviceObject *obj)
{
    HDF_LOGD("#### in %s\n", __func__);
    return HDF_SUCCESS;
}
int32_t myInit(struct HdfDeviceObject *obj)
{
    HDF_LOGD("#### in %s\n", __func__);
    return HDF_SUCCESS;
}
void myRelease(struct HdfDeviceObject *obj)
{
    HDF_LOGD("#### in %s\n", __func__);
}

struct HdfDriverEntry myTestEntry = {
    .Bind = myBind,
    .Init = myInit,
    .Release = myRelease,
    .moduleName = "myTestDriver",
    .moduleVersion = 1
};
HDF_INIT(myTestEntry);

为了将myTestDriver.c源文件编译进系统镜像,修改drivers/hdf_core/adapter/khdf/liteos/platform目录下的BUILD.gn,在42行增加以下内容:

c 复制代码
 42     "src/myTestDriver.c"

修改drivers/hdf_core/adapter/khdf/liteos/platform目录下的Makefile,在38行增加以下内容:

c 复制代码
 38 LOCAL_SRCS += ./src/myTestDriver.c

完成后就可以编译OpenHarmony系统,编译完成后在out输出目录下找到相应的.o文件则表示驱动源文件已成功编译,如图所示:

但这时先不急着烧录更新系统镜像,因驱动并不是编译进系统镜像就表示产生作用的,设备驱动还需要在.hcs文件中有同样moduleName的设备节点描述,匹配上后驱动才会启动。

2. HCS设备节点描述

OpenHarmony官方文档对hcs语法提供了非常详细的指导,这里不表。匹配设备驱动的设备节点描述如下:

c 复制代码
      myTestHost :: host{ //继承template模板host
            hostName = "myTestHost";    // host名称
            priority = 100;        // host启动优先级(0-200),值越大优先级越低
            testDevice :: device {     //testDevice设备节点继承于template模板device
                device0 :: deviceNode {   //节点device0继承于template模板deviceNode
                    policy = 2;      // policy字段是驱动服务发布的策略,2表示向用户态提供服务接口
                    priority = 100;       // 驱动启动优先级(0-200),值越大优先级越低
                    preload = 0;             //驱动在系统启动时加载。
                    permission = 0664;       //驱动创建设备节点权限
                    moduleName = "myTestDriver"; //此名必须与设备驱动的moduleName一致才会匹配。
                    serviceName = "myTestService";//驱动对外发布服务的名称,应用程序通过此名获取设备驱动提供的服务,从而交互操作,所以此服务名必须唯一。
                }
            }
        }

下面可选使用模拟设备或Hi3516开发板进行验证:

1). 如使用OpenHarmony的qemu模拟设备,则在device/qemu/arm_virt/liteos_a/hdf_config/device_info/device_info.hcs尾部增加设备节点描述,如图所示:

完成后编译系统,启动虚拟设备后,执行命令"hilogcat",即可查看到设备驱动函数的输出信息如图所示:

2). 如使用Hi3516开发板,则在vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs尾部增加设备节点描述,如图所示:

这里注意即使编译并更新使用新系统镜像也无法查看到设备驱动输出信息的,因系统在启动时通过uart接口输出hilog信息,并且uart接口速率无法及时输出大量信息,导致发生多次"hilog ringbuffer full, drop 4 line(s) log"爆缓冲区的状况,所以无法像模拟设备一样查看到设备驱动函数的输出。

3. 设备增加HDI调用接口服务

修改myTestDriver.c驱动源文件内容,增加HDI调用接口服务函数,增加与修改内容如下:

c 复制代码
//增加myDispatch函数,在应用程序通过服务Dispatch时触发调用
static int32_t myDispatch(
    struct HdfDeviceIoClient *client, int id, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    HDF_LOGD("### in %s : %d\n", __func__, id);
    return HDF_SUCCESS;
}

int32_t myBind(struct HdfDeviceObject *obj) //修改
{
    //每个struct IDeviceIoService对象表示一个HDI调用服务对象
    static struct IDeviceIoService testService = {
        .Dispatch = myDispatch, //指定由myDispatch函数处理服务
    };
    obj->service = &testService; //指定设备obj使用testService服务对象
    HDF_LOGD("#### in %s\n", __func__);

    return HDF_SUCCESS;
}

4. 应用程序通过HDI调用接口访问设备驱动

编写应用程序,实现通过hcs设备节点描述的moduleName获取设备驱动服务,并传递参数。源文件mytest.c内容如下:

c 复制代码
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "hdf_io_service_if.h"

int main(void)
{  //通过moduleName获取设备驱动的服务对象
    struct HdfIoService *serv = HdfIoServiceBind("myTestService");
    if (serv == NULL) {
        printf("fail to get service\n");
        return 1;
    }


    for (int n = 0; n < 20; n++)
    {  //向设备驱动服务传递参数,触发调用驱动的myDispatch函数
        int ret = serv->dispatcher->Dispatch(&serv->object, n, NULL, NULL);
        if (ret < 0)
            break;
        sleep(5);
    }
    printf("test end\n");
    return 0;
}

应用程序编译的BUILD.gn内容如下:

c 复制代码
hdf_framework_path = "../../../../../framework"

executable("mytest") {
  sources = [ "mytest.c" ]

  include_dirs = [
    "$hdf_framework_path/ability/sbuf/include",
    "$hdf_framework_path/core/shared/include",
    "$hdf_framework_path/core/host/include",
    "$hdf_framework_path/core/master/include",
    "$hdf_framework_path/include/core",
    "$hdf_framework_path/include/utils",
    "$hdf_framework_path/utils/include",
    "$hdf_framework_path/include/osal",
    "//third_party/bounds_checking_function/include",
    "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
  ]

  deps = [
    "//drivers/hdf_core/adapter/uhdf/manager:hdf_core",
    "//drivers/hdf_core/adapter/uhdf/posix:hdf_posix_osal",
    "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
  ]

  public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ]
  defines = [ "__USER__" ]
}

5. 应用程序运行效果

编译并更新使用新系统镜像后,执行bin目录下的mytest程序,输出信息如图所示:

相关推荐
晚秋大魔王2 天前
openharmony 4.1 运行busybox工具包(保姆教程)
openharmony·busybox·开源鸿蒙
雪域迷影7 天前
OpenHarmony之电源模式定制开发指导
openharmony·电源模式
智驾8 天前
Openharmony 和 HarmonyOS 区别?
harmonyos·openharmony
TARDIS_202011 天前
OpenHarmony-Risc-V上运行openBLAS中的benchmark
risc-v·openharmony
少年的云河月12 天前
OpenHarmony Camera开发指导(五):相机预览功能(ArkTS)
harmonyos·openharmony·camera·相机开发
少年的云河月15 天前
OpenHarmony Camera开发指导(四):相机会话管理(ArkTS)
harmonyos·相机·openharmony·camera
夜星辰202317 天前
最新 OpenHarmony 系统一二级目录整理
openharmony
ursamjnor18 天前
基于 OpenHarmony 5.0 的星闪轻量型设备应用开发-Ch1 开发环境搭建
openharmony·星闪·轻量型设备开发
少年的云河月19 天前
OpenHarmony Camera组件简介
harmonyos·相机·openharmony·camera