理解HarmonyOS驱动框架,用户态APP和内核态驱动之间的通信机制。
具体运行结果为用户态APP向驱动发送123号cmd,内核态读取该cmd对应的字符串data,并打印出来。然后内核态驱动程序向用户态发送事件,传递的参数为reply。用户态APP通过事件监听函数获取内核态发送的消息打印出来。
这跟Linux的驱动框架不一样,在Linux中,APP打开设备节点后,APP调用的read函数会直接进入内核态调用驱动的read函数。
在liteos-a中使用HDF时,APP需要先获得服务,然后调用服务的Dispatch函数:它可以向驱动发送数据、获得返回结果。
在HDF中,一个驱动被抽象为“HdfDriverEntry”,代码如下:
上述代码中,使用HDF_INIT定义了某些段属性的结构体,内核启动后会注册这个HdfDriverEntry。
重要的是其中的Bind函数,Init和Release函数顾名思义就是初始化和释放相关资源,这里好像和HDF_INIT有些冲突,示例函数用空函数来替代它们了。代码如下:
在驱动初始化函数HdfSampleDriverBind中会绑定一个服务函数,这个服务函数用来处理用户态APP发送过来的消息。绑定过程是给IDeviceIoService这个结构体的Dispatch元素赋值来实现的。如图所示:
你可以认为Dispatch函数相当于ioctl,在Linux中通过ioctl(fd, cmd, arg)来操作驱动。
在liteos-a中通过service->>dispatcher->Dispatch(ojb, cmd, data, replay)来操作驱动。把驱动放入内核
vendor/huawei/hdf/sample
Kconfig如下:
Makefile如下:
如下图增加最后一行:
上一级的Kconfig:
# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
source "../../vendor/hisi/hi35xx/platform/Kconfig"
source "../../vendor/huawei/hdf/wifi/driver/Kconfig"
source "../../vendor/huawei/hdf/input/driver/Kconfig"
source "../../vendor/huawei/hdf/display/driver/Kconfig"
source "../../vendor/huawei/hdf/sample/Kconfig"
目录:vendor/hisi/hi35xx/ hi3516dv300/config /sample/sample_config.hcs:
源码:
root {
module = "sample_driver";
author = "zhangfeidz for test";
serviceName = "sample_service";
}
目录:vendor/hisi/hi35xx/ hi3516dv300/config /device_info/device_info.hcs:
目录:vendor/huawei/hdf/hdf_vendor.mk:
增加两行:
APP先获得服务,在调用Dispatch即可。需要注意的是里面用的是HdfSBuf传递数据。
一下是hello_test.c的源码。
要分配两个HdfBuf:data、reply。data用于向驱动传参数,reply用来保存驱动返回的数据。
代码如下:
先在整个系统源码的根目录下创建一个子目录,比如myapp,在里面放入sample_test.c。
再修改 drivers/hdf/lite/manager/BUILD.gn。
源码如下:
import("//build/lite/config/component/lite_component.gni")
HDF_FRAMEWORKS = "//drivers/hdf/frameworks"
shared_library("hdf_core") {
sources = [
"$HDF_FRAMEWORKS/core/shared/src/hdf_io_service.c",
"$HDF_FRAMEWORKS/ability/sbuf/src/hdf_sbuf.c",
"../adapter/syscall/src/hdf_syscall_adapter.c"
]
include_dirs = [
"../adapter/syscall/include",
"../adapter/vnode/include",
"$HDF_FRAMEWORKS/core/shared/include",
"$HDF_FRAMEWORKS/core/host/include",
"$HDF_FRAMEWORKS/core/manager/include",
"$HDF_FRAMEWORKS/ability/sbuf/include",
"$HDF_FRAMEWORKS/include/core",
"$HDF_FRAMEWORKS/include/utils",
"$HDF_FRAMEWORKS/utils/include",
"$HDF_FRAMEWORKS/include/osal",
"//third_party/bounds_checking_function/include",
]
deps = [
"//drivers/hdf/lite/adapter/osal/posix:hdf_posix_osal",
"//third_party/bounds_checking_function:libsec_shared",
]
defines = [
"__USER__",
]
cflags = [
"-Wall",
"-Wextra",
"-Werror",
"-fsigned-char",
"-fno-common",
"-fno-strict-aliasing",
]
}
executable("sample_test") {
sources = [
"//myapp/sample_test.c"
]
include_dirs = [
"../adapter/syscall/include",
"../adapter/vnode/include","$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",
"//third_party/bounds_checking_function/include",
]
deps = [
"//drivers/hdf/lite/manager:hdf_core",
"//drivers/hdf/lite/adapter/osal/posix:hdf_posix_osal",
]
public_deps = [
"//third_party/bounds_checking_function:libsec_shared",
]
defines = [
"__USER__",
]
cflags = [
"-Wall",
"-Wextra",
"-Werror",
]
}
lite_component("hdf_manager") {
features = [
":hdf_core",
":sample_test",
]
}
sample_test.c文件信息加入BUILD.gn文件后,编译系统时,就会按照指定的规则(程序源码,编译依赖,生成可执行程序的名字,以及可执行程序在HarmonyOS系统中的目录)进行编译。
Hi3516dv300开发板: python build.py ipcamera_hi3516dv300 -b debug
Hi3518ev300开发板: python build.py ipcamera_hi3518ev300 -b debug
Hi3516dv300开发板: python build.py ipcamera –p hi3516dv300_liteos_a
Hi3518ev300开发板: python build.py ipcamera –p hi3518ev300_liteos_a
网口烧录配置
在uboot里面输入命令,配置启动设置,具体方法如下。
命令1:
Hi3516dv300开发板:
setenv bootcmd 'sf probe 0;sf read 0x80000000 0x100000 0x600000;go 0x80000000';saveenv;
Hi3518ev300开发板:
setenv bootcmd 'sf probe 0;sf read 0x40000000 0x100000 0x600000;go 0x40000000';saveenv;
这条命令作用是选择从0x80000000(或者0x40000000)这个地址启动HarmonyOS。在flash内部,0x100000是起始地址,0x6000000是HarmonyOS_Image.bin的大小(本示例中,该文档大小为6M)
命令2:
setenv bootargs "ttyAMA0,115200n8 root=flash fstype=jffs2 rw rootaddr=7M rootsize=8M";saveenv;
该命令的作用是进行串口配置。rootaddr是文件系统的起始地址,rootsize是文件的大小。实际开发时,请具体情况具体分析。
配置完成后,输入命令 go 0x80000000,就可以进入Harmony系统了。
Harmony系统目录结构如下:
进入bin文件夹,运行sample_test程序:
注:本文档或视频中所有的图片,代码截图仅供参考,具体以HarmonyOS官网发布的最新内容为准。
张飞 张飞实战电子高级工程师
213863学员
张飞老师,高级硬件工程师,2005年起从事电子研发,在上海某研究所学习近一年。2008年至今在大型外资企业担任首席工程师、专家,研发企业未来3至5年的产品。还担任过课长、经理等职务。视频教程将自己这十多年从事一线研发的经验和心得与大家分享,带领大家一起学习如何设计和优化威廉希尔官方网站 。