HDF驱动框架探路(二):openharmony最新源码,打通应用态到内核态 原创 精华

Mr_qzk
发布于 2021-11-25 15:17
浏览
10收藏

【本文正在参与优质创作者激励】
老规矩还是将最终希望跑出来的效果放出来。如下:
HDF驱动框架探路(二):openharmony最新源码,打通应用态到内核态-鸿蒙开发者社区

@toc

前言

  • 1.首先本文章的源码是2021.11.25拉的openharmony的master分支。之前也有一些大神基于3516应用态打通到了内核态,不过都很久远了,尤其是3.0LTS发布之后,整个框架都改动过了,按照大神们的操作我这边基于最新的源码都没有测试成功。有大佬可以留言指导一拨儿。
  • 2.本文章是基于Hi3516轻量系统来打造的。

应用态打通内核态的总体框架图

HDF驱动框架探路(二):openharmony最新源码,打通应用态到内核态-鸿蒙开发者社区
从上图可以很直观的看出驱动开发的过程中基于linux开发和基于openharmony开发的最大区别

  • 1.linux驱动开发中会涉及到应用层的glic等,以及驱动层的内核函数调用,但是在openharmony这些以及都被HDF框架给隐藏起来了,所以我们只需要根据HDF框架来进行openharmony框架开发,就可以了。
  • 2.openharmony应用层其实是调用了HDF框架的驱动消息机制

1.应用程序

2.1 应用层业务代码

  • 1.在源码根目录下新建myapp目录
  • 2.然后进入myapp目录新建helloworld_test.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"

#define HDF_LOG_TAG "sample_test"
#define SAMPLE_SERVICE_NAME "GPIO_TEST"

#define SAMPLE_WRITE_READ 0

int g_replyFlag = 0;

static int OnDevEventReceived(void *priv,  uint32_t id, struct HdfSBuf *data)
{
    const char *string = HdfSbufReadString(data);
    if (string == NULL) {
        HDF_LOGE("fail to read string in event data");
        g_replyFlag = 1;
        return HDF_FAILURE;
    }
    HDF_LOGE("%s: dev event received: %u %s",  (char *)priv, id, string);
    g_replyFlag = 1;
    return HDF_SUCCESS;
}

static int SendEvent(struct HdfIoService *serv, char *eventData)
{
    int ret = 0;
    struct HdfSBuf *data = HdfSBufObtainDefaultSize();
    if (data == NULL) {
        HDF_LOGE("fail to obtain sbuf data");
        return 1;
    }

    struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
    if (reply == NULL) {
        HDF_LOGE("fail to obtain sbuf reply");
        ret = HDF_DEV_ERR_NO_MEMORY;
        goto out;
    }

    if (!HdfSbufWriteString(data, eventData)) {
        HDF_LOGE("fail to write sbuf");
        ret = HDF_FAILURE;
        goto out;
    }

    ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("fail to send service call");
        goto out;
    }

    int replyData = 0;
    if (!HdfSbufReadInt32(reply, &replyData)) {
        HDF_LOGE("fail to get service call reply");
        ret = HDF_ERR_INVALID_OBJECT;
        goto out;
    }
    HDF_LOGE("Get reply is: %d", replyData);
out:
    HdfSBufRecycle(data);
    HdfSBufRecycle(reply);
    return ret;
}

int main()
{
    char *sendData = "hi";
    struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME);
    if (serv == NULL) {
        HDF_LOGE("fail to get service %s", SAMPLE_SERVICE_NAME);
        return HDF_FAILURE;
    }
    HDF_LOGE("success to get service %s", SAMPLE_SERVICE_NAME);

    static struct HdfDevEventlistener listener = {
        .callBack = OnDevEventReceived,
        .priv ="Service0"
    };

    if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS) {
        HDF_LOGE("fail to register event listener");
        return HDF_FAILURE;
    }
    HDF_LOGE("success to register event listener");
    if (SendEvent(serv, sendData)) {
        HDF_LOGE("fail to send event");
        return HDF_FAILURE;
    }

    /* wait for event receive event finishing */
    while (g_replyFlag == 0) {
        sleep(1);
    }

    if (HdfDeviceUnregisterEventListener(serv, &listener)) {
        HDF_LOGE("fail to  unregister listener");
        return HDF_FAILURE;
    }

    HdfIoServiceRecycle(serv);
    return HDF_SUCCESS;
}

1.2 应用层业务代码以可执行文件编译进系统

  • 进入源码目录找到drivers/adapter/uhdf/manager/BUILD.gn 文件,然后在文件末尾拷贝下述代码。
HDF_FRAMEWORKS = "//drivers/framework"

executable("helloworld_test") {
  sources = ["//myapp/helloworld_test.c" ]
  include_dirs = [
    "$HDF_FRAMEWORKS/ability/sbuf/include",
    "$HDF_FRAMEWORKS/core/shared/include",
    "$HDF_FRAMEWORKS/core/host/include",
    "$HDF_FRAMEWORKS/core/master/include",
    "$HDF_FRAMEWORKS/include/core",
    "$HDF_FRAMEWORKS/include/utils",
    "$HDF_FRAMEWORKS/utils/include",
    "$HDF_FRAMEWORKS/include/osal",
    "//drivers/adapter/uhdf/posix/include",
    "//third_party/bounds_checking_function/include",
    "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
  ]

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

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

  cflags = [
    "-Wall", 
    "-Wextra",
    "-Wno-format",
    "-Wno-format-extra-args",
  ]
}

2.驱动代码

这里驱动是直接引用了源码中已经存在的一个驱动程序:GPIO_TEST

2.1 驱动业务层代码

  • 进入源码目录,找到drivers/framework/test/unittest/platform/common/gpio_driver_test.c文件,然后对比下图进行修改。
    HDF驱动框架探路(二):openharmony最新源码,打通应用态到内核态-鸿蒙开发者社区

执行hb build -f进行编译,然后烧录,接着打开串口就可以看到效果了

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2021-11-25 15:17:25修改
7
收藏 10
回复
举报
4条回复
按时间正序
/
按时间倒序
Whyalone
Whyalone

一个不懂C的人路过,虽然看不懂,但是牛批就对了

========

为什么要有用户态和内核态?

由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 -- 用户态和内核态。

2
回复
2021-11-26 10:33:23
Mr_qzk
Mr_qzk

你的这个自问自答也很牛批

回复
2021-11-30 09:57:28
mb622ae3215c264
mb622ae3215c264

你好,我按照你的文章的操作,/system/bin下面并没有可执行文件,请问是还有什么东西需要添加配置的么

回复
2022-3-14 16:10:58
GG2345
GG2345 回复了 mb622ae3215c264
你好,我按照你的文章的操作,/system/bin下面并没有可执行文件,请问是还有什么东西需要添加配置的么

先看你开发机编译目录下的out目录下,有没有生成二进制文件,例如用 qemu_small_system_demo 模拟器设备做实验时,应该在 out/arm_virt/qemu_small_system_demo/rootfs/bin 下生成相应的二进制。

 

如果生成了,再确定固件有没有重新生成,例如我用 qemu-run 模拟器做一些实验时,flash.img 就不会重新生成,而需要用 ./qemu-run -f

 

如果没生成,仿照已有的 app 写就是了。

回复
2022-3-31 20:22:58
回复
    相关推荐