树莓派4B编写HDF驱动示例 原创 精华

发布于 2021-12-31 12:45
浏览
3收藏

【本文正在参与优质创作者激励】

前言

前段时间已经在树莓派4B成功加入了HDF驱动框架,帖子链接。得用HDF编写个自己的驱动来测试下移植的效果。不说了代码最实在,看代码吧。

树莓派4B编写HDF驱动示例-开源基础软件社区

1.内核态驱动代码

一个简单的测试驱动,可以认为是串口驱动。因为在linux内核下,所以驱动放置在linux\platform\uart目录下。

drivers\adapter\khdf\linux\platform\uart\my_hdf_uart.c

#include "hdf_device_desc.h"    // HDF框架对驱动开发相关能力接口的头文件
#include "hdf_log.h"            // HDF 框架提供的日志接口头文件

#define HDF_LOG_TAG "my_hdf_uart"   // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签

// 【3.1驱动消息机制管理】Dispatch是用来处理用户态发下来的消息
int32_t MyUartDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    HDF_LOGE("%s::enter", __func__);
    HDF_LOGE("get cmdId::%d",cmdId);
    return HDF_SUCCESS;
}

// 【1.驱动开发】驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架
int32_t MyHdfUartDriverBind(struct HdfDeviceObject *deviceObject)
{
    HDF_LOGE("%s::enter", __func__);

    // 【2.驱动服务管理】deviceObject为HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口
    if (deviceObject == NULL) {
        HDF_LOGE("My Uart device object is null!");
        return HDF_FAILURE;
    }
    static struct IDeviceIoService testService = {
        .Dispatch = MyUartDriverDispatch,   // 【3.2驱动消息机制管理】在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法
        .Open = NULL,                       // 【2.驱动服务管理】驱动提供的其他服务。
        .Release = NULL,
        // .ServiceA = SampleDriverServiceA,
    };
    deviceObject->service = &testService;

    return HDF_SUCCESS;
}

// 【1.驱动开发】驱动自身业务初始的接口
int32_t MyHdfUartDriverInit(struct HdfDeviceObject *deviceObject)
{
    HDF_LOGE("%s::enter", __func__); 
    HDF_LOGD("Uart driver bind success");       
    return 0;
}
static int32_t MyUartParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
{
    HDF_LOGE("%s::enter", __func__);
    return 0;
}


// 【1.驱动开发】驱动资源释放的接口
void MyHdfUartDriverRelease(struct HdfDeviceObject *deviceObject)
{
    HDF_LOGE("%s::enter", __func__);
    return;
}

// 【1.驱动开发】定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量
struct HdfDriverEntry g_myhdfUartDriverEntry = {
    .moduleVersion = 1,
    .moduleName = "my_hdf_uart",
    .Bind = MyHdfUartDriverBind,
    .Init = MyHdfUartDriverInit,
    .Release = MyHdfUartDriverRelease,
};

// 【1.驱动开发】调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
HDF_INIT(g_myhdfUartDriverEntry);

drivers\adapter\khdf\linux\platform\uart\Makefile:将驱动加入内核编译

- uart_adapter.o

+ uart_adapter.o \
+ my_hdf_uart.o

2.添加驱动配置文件

vendor\raspberrypi\RPI4B\hdf_config\khdf\device_info\device_info.hcs

# device_uart :: device 下添加

device2 :: deviceNode {
    policy = 2;
    permission = 0644;
    priority = 40;
    moduleName = "my_hdf_uart";
    serviceName = "my_hdf_uart_service";
}

3.用户态HDF驱动交互验证

applications\standard\app\myuarttest.c:用户态主程序,主要代码已经添加注释了。

#include <utils/hdf_log.h>
#include <core/hdf_io_service_if.h>
#include "hdf_sbuf.h"

#define HDF_LOG_TAG "my_hdf_uart"
#define SAMPLE_SERVICE_NAME "my_hdf_uart_service"

#define SAMPLE_WRITE_READ 1001   // 【驱动消息机制管理】读写操作码,驱动定义消息处理函数中的cmd类型

int main()
{
    HDF_LOGE("%s::enter", __func__);
    int ret = 0;

    // 用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息。
    struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME);  // 【3驱动消息机制管理】用户态(通过服务名)获取服务接口
    if (serv == NULL) {
        HDF_LOGE("fail to get service %s", SAMPLE_SERVICE_NAME);
        return HDF_FAILURE;
    }
    
    char *sendData = "";
    struct HdfSBuf *data = HdfSBufObtainDefaultSize();      // 存放要发送的数据
    if (!HdfSbufWriteString(data, sendData)) {              // 发送的内容赋值
        HDF_LOGE("fail to write sbuf");
        ret = HDF_FAILURE;
    }

    struct HdfSBuf *reply = HdfSBufObtainDefaultSize();                                         // 存放返回的数据
    ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);        // 发送消息到驱动
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("fail to send service call");
    }

    HdfIoServiceRecycle(serv);
    return HDF_SUCCESS;
}

applications\standard\app\BUILD.gn:编写构建脚本

import("//build/ohos.gni")
import("//drivers/adapter/uhdf2/uhdf.gni")

ohos_executable("myuarttest") {
  sources = [
    "myuarttest.c"
  ]
  include_dirs = [    
    "//drivers/framework/include",                                  # <utils/hdf_log.h> <core/hdf_io_service_if.h>
    "//drivers/adapter/uhdf2/osal/include",                         # hdf_log_adapter.h
    "//base/hiviewdfx/hilog/interfaces/native/innerkits/include",   # <hilog/log.h>
    "//drivers/framework/ability/sbuf/include",                     # hdf_sbuf.h
    "//drivers/framework/include/utils",                            # hdf_base.h
  ]
  deps = [
    "//drivers/adapter/uhdf2/osal:libhdf_utils",                    # hdf_log_adapter.h
    "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog"   # <hilog/log.h>
  ]
  subsystem_name = "applications"
  part_name = "prebuilt_hap"
}

applications\standard\hap\ohos.build:最后将app加入编译框架

+ "//applications/standard/app:myuarttest",

4.测试

最后执行用户态的myuarttest程序,就可以测试驱动是否添加成功了。

树莓派4B编写HDF驱动示例-开源基础软件社区

用户态只需要发送cmdId比如1001,然后内核驱动程序根据cmdID执行相应的操作即可。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
6
收藏 3
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐