From 0546ba8635b2121f8664ddee0f4f721d448cf273 Mon Sep 17 00:00:00 2001 From: liyan Date: Thu, 7 Jul 2022 11:43:02 +0000 Subject: [PATCH] =?UTF-8?q?=E8=A7=84=E8=8C=83=E6=80=A7=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=20Signed-off-by:=20li-yan339=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../driver/driver-hdf-development.md | 202 +++++++++--------- 1 file changed, 105 insertions(+), 97 deletions(-) diff --git a/zh-cn/device-dev/driver/driver-hdf-development.md b/zh-cn/device-dev/driver/driver-hdf-development.md index 49bd0a14ab..c1abcd7db0 100755 --- a/zh-cn/device-dev/driver/driver-hdf-development.md +++ b/zh-cn/device-dev/driver/driver-hdf-development.md @@ -3,7 +3,7 @@ ## 驱动模型介绍 -HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个node。HDF驱动模型如下图所示: +HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个Host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个Node。HDF驱动模型如下图所示: **图1** HDF驱动模型 @@ -12,28 +12,28 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心 ## 驱动开发步骤 -基于HDF框架进行驱动的开发主要分为两个部分,驱动实现和驱动配置。详细开发流程如下所示: +基于HDF框架的驱动开发主要分为三个部分:驱动实现、驱动编译和驱动配置。详细开发流程如下所示: 1. 驱动实现 - 驱动实现包含驱动业务代码和驱动入口注册,具体写法如下: + 驱动实现包含驱动业务代码实现和驱动入口注册,具体写法如下: - 驱动业务代码 ``` - #include "hdf_device_desc.h" // HDF框架对驱动开发相关能力接口的头文件 - #include "hdf_log.h" // HDF框架提供的日志接口头文件 + #include "hdf_device_desc.h" // HDF框架对驱动开发相关能力接口的头文件 + #include "hdf_log.h" // HDF框架提供的日志接口头文件 - #define HDF_LOG_TAG "sample_driver" // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签 + #define HDF_LOG_TAG "sample_driver" // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签。 - // 驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架 + // 驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架。 int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) { HDF_LOGD("Sample driver bind success"); return 0; } - // 驱动自身业务初始的接口 + // 驱动自身业务初始化的接口 int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) { HDF_LOGD("Sample driver Init success"); @@ -50,7 +50,7 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心 - 驱动入口注册到HDF框架 ``` - // 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量 + // 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量。 struct HdfDriverEntry g_sampleDriverEntry = { .moduleVersion = 1, .moduleName = "sample_driver", @@ -59,93 +59,94 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心 .Release = HdfSampleDriverRelease, }; - // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 + // 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动;当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 HDF_INIT(g_sampleDriverEntry); ``` 2. 驱动编译 - - liteos - 涉及makefile和BUILD.gn修改: + - LiteOS - - makefile部分: + 涉及Makefile和BUILD.gn修改: - 驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。 + - Makefile部分: - - ``` - include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk #导入hdf预定义内容,必需 - MODULE_NAME := #生成的结果文件 - LOCAL_INCLUDE := #本驱动的头文件目录 - LOCAL_SRCS := #本驱动的源代码文件 - LOCAL_CFLAGS := #自定义的编译选项 - include $(HDF_DRIVER) #导入Makefile模板完成编译 - ``` + 驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。 + + + ``` + include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk # 【必需】导入hdf预定义内容 + MODULE_NAME := #生成的结果文件 + LOCAL_INCLUDE := #本驱动的头文件目录 + LOCAL_SRCS := #本驱动的源代码文件 + LOCAL_CFLAGS := #自定义的编译选项 + include $(HDF_DRIVER) #导入Makefile模板完成编译 + ``` - 编译结果文件链接到内核镜像,添加到drivers/adapter/khdf/liteos目录下的hdf_lite.mk里面,示例如下: + 编译结果文件链接到内核镜像,添加到**drivers/adapter/khdf/liteos**目录下的**hdf_lite.mk**里面,示例如下: - ``` - LITEOS_BASELIB += -lxxx #链接生成的静态库 - LIB_SUBDIRS += #驱动代码Makefile的目录 - ``` + ``` + LITEOS_BASELIB += -lxxx #链接生成的静态库 + LIB_SUBDIRS += #驱动代码Makefile的目录 + ``` - - BUILD.gn部分: + - BUILD.gn部分: - 添加模块BUILD.gn参考定义如下内容: + 添加模块BUILD.gn参考定义如下内容: - ``` - import("//build/lite/config/component/lite_component.gni") - import("//drivers/adapter/khdf/liteos/hdf.gni") - module_switch = defined(LOSCFG_DRIVERS_HDF_xxx) - module_name = "xxx" - hdf_driver(module_name) { - sources = [ - "xxx/xxx/xxx.c", #模块要编译的源码文件 - ] - public_configs = [ ":public" ] #使用依赖的头文件配置 - } - config("public") { #定义依赖的头文件配置 - include_dirs = [ - "xxx/xxx/xxx", #依赖的头文件目录 - ] - } - ``` - - 把新增模块的BUILD.gn所在的目录添加到/drivers/adapter/khdf/liteos/BUILD.gn里面: + ``` + import("//build/lite/config/component/lite_component.gni") + import("//drivers/adapter/khdf/liteos/hdf.gni") + module_switch = defined(LOSCFG_DRIVERS_HDF_xxx) + module_name = "xxx" + hdf_driver(module_name) { + sources = [ + "xxx/xxx/xxx.c", #模块要编译的源码文件 + ] + public_configs = [ ":public" ] #使用依赖的头文件配置 + } + config("public") { #定义依赖的头文件配置 + include_dirs = [ + "xxx/xxx/xxx", #依赖的头文件目录 + ] + } + ``` + + 把新增模块的BUILD.gn所在的目录添加到**/drivers/adapter/khdf/liteos/BUILD.gn**里面: - ``` - group("liteos") { - public_deps = [ ":$module_name" ] - deps = [ - "xxx/xxx", #新增模块BUILD.gn所在的目录,目录结构相对于/drivers/adapter/khdf/liteos - ] - } - ``` - - linux - - 如果需要定义模块控制宏,需要在模块目录xxx里面添加Kconfig文件,并把Kconfig文件路径添加到drivers/adapter/khdf/linux/Kconfig里面: + ``` + group("liteos") { + public_deps = [ ":$module_name" ] + deps = [ + "xxx/xxx", #新增模块BUILD.gn所在的目录,目录结构相对于/drivers/adapter/khdf/liteos + ] + } + ``` + - Linux + + 如果需要定义模块控制宏,需要在模块目录xxx里面添加Kconfig文件,并把Kconfig文件路径添加到**drivers/adapter/khdf/linux/Kconfig**里面: - ``` - source "drivers/hdf/khdf/xxx/Kconfig" #目录为hdf模块软链接到kernel里面的目录 - ``` + ``` + source "drivers/hdf/khdf/xxx/Kconfig" #目录为hdf模块软链接到kernel里面的目录 + ``` - 添加模块目录到drivers/adapter/khdf/linux/Makefile: + 添加模块目录到**drivers/adapter/khdf/linux/Makefile**: - ``` - obj-$(CONFIG_DRIVERS_HDF) += xxx/ - ``` + ``` + obj-$(CONFIG_DRIVERS_HDF) += xxx/ + ``` - 在模块目录xxx里面添加Makefile文件,在Makefile文件里面添加模块代码编译规则: + 在模块目录xxx里面添加Makefile文件,在Makefile文件里面添加模块代码编译规则: - ``` - obj-y += xxx.o - ``` + ``` + obj-y += xxx.o + ``` 3. 驱动配置 @@ -155,19 +156,19 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心 - 驱动设备描述(必选) - HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描述,驱动的设备描述填写如下所示: + HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描述。驱动的设备描述填写如下所示: ``` root { device_info { match_attr = "hdf_manager"; - template host { // host模板,继承该模板的节点(如下sample_host)如果使用模板中的默认值,则节点字段可以缺省 + template host { // host模板,继承该模板的节点(如下sample_host)如果使用模板中的默认值,则节点字段可以缺省。 hostName = ""; priority = 100; - uid = ""; // 用户态进程uid,缺省为空,会被配置为hostName的定义值,即普通用户 - gid = ""; // 用户态进程gid,缺省为空,会被配置为hostName的定义值,即普通用户组 - caps = [""]; // 用户态进程Linux capabilities配置,缺省为空,需要业务模块按照业务需要进行配置 + uid = ""; // 用户态进程uid,缺省为空,会被配置为hostName的定义值,即普通用户。 + gid = ""; // 用户态进程gid,缺省为空,会被配置为hostName的定义值,即普通用户组。 + caps = [""]; // 用户态进程Linux capabilities配置,缺省为空,需要业务模块按照业务需要进行配置。 template device { template deviceNode { policy = 0; @@ -181,39 +182,41 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心 } } sample_host :: host{ - hostName = "host0"; // host名称,host节点是用来存放某一类驱动的容器 - priority = 100; // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序 - caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; // 用户态进程Linux capabilities配置 + hostName = "host0"; // host名称,host节点是用来存放某一类驱动的容器。 + priority = 100; // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序。 + caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; // 用户态进程Linux capabilities配置。 device_sample :: device { // sample设备节点 device0 :: deviceNode { // sample驱动的DeviceNode节点 - policy = 1; // policy字段是驱动服务发布的策略,在驱动服务管理章节有详细介绍 - priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序 - preload = 0; // 驱动按需加载字段,在本章节最后的说明有详细介绍 + policy = 1; // policy字段是驱动服务发布的策略,在驱动服务管理章节有详细介绍。 + priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序。 + preload = 0; // 驱动按需加载字段,在本章节最后的说明有详细介绍。 permission = 0664; // 驱动创建设备节点权限 - moduleName = "sample_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 - serviceName = "sample_service"; // 驱动对外发布服务的名称,必须唯一 - deviceMatchAttr = "sample_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 + moduleName = "sample_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致。 + serviceName = "sample_service"; // 驱动对外发布服务的名称,必须唯一。 + deviceMatchAttr = "sample_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等。 } } } } } ``` - 说明: - - uid、gid、caps等配置项是用户态驱动的启动配置,内核态不用配置。 - - 根据进程权限最小化设计原则,业务模块uid、gid不用配置,如上面的sample_host,使用普通用户权限,即uid和gid被定义为hostName的定义值。 - - 如果普通用户权限不能满足业务要求,需要把uid、gid定义为system或者root权限时,请找安全专家进行评审。 - - 进程的uid在文件base/startup/init_lite/services/etc/passwd中配置,进程的gid在文件base/startup/init_lite/services/etc/group中配置,进程uid和gid配置参考:[系统服务用户组添加方法](https://gitee.com/openharmony/startup_init_lite/wikis)。 + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
+ > + > - uid、gid、caps等配置项是用户态驱动的启动配置,内核态不用配置。 + > + > - 根据进程权限最小化设计原则,业务模块uid、gid不用配置,如上面的sample_host,使用普通用户权限,即uid和gid被定义为hostName的定义值。 + > + > - 如果普通用户权限不能满足业务要求,需要把uid、gid定义为system或者root权限时,请找安全专家进行评审。 + > + > - 进程的uid在文件**base/startup/init_lite/services/etc/passwd**中配置,进程的gid在文件**base/startup/init_lite/services/etc/group**中配置,进程uid和gid配置参考:[系统服务用户组添加方法](https://gitee.com/openharmony/startup_init_lite/wikis)。 + > + > - caps值:比如业务模块要配置CAP_DAC_OVERRIDE,此处需要填写caps = ["DAC_OVERRIDE"],不能填写为caps = ["CAP_DAC_OVERRIDE"]。 - caps值:比如业务模块要配置CAP_DAC_OVERRIDE,此处需要填写 caps = ["DAC_OVERRIDE"],不能填写为caps = ["CAP_DAC_OVERRIDE"]。 - 驱动私有配置信息(可选) - 如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject中的property里面,通过Bind和Init(参考步骤1)传递给驱动,驱动的配置信息示例如下: + 如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息。HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject中的property里面,通过Bind和Init(参考步骤1)传递给驱动。驱动的配置信息示例如下: ``` @@ -249,7 +252,12 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心 > } DevicePreload; > ``` > -> 配置文件中preload字段配成0(DEVICE_PRELOAD_ENABLE),则系统启动过程中默认加载;配成1(DEVICE_PRELOAD_ENABLE_STEP2),当系统支持快启的时候,则在系统完成之后再加载这一类驱动,否则和DEVICE_PRELOAD_ENABLE含义相同;配成2(DEVICE_PRELOAD_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务(参考[消息机制](../driver/driver-hdf-message-management.md))时,如果驱动服务不存在,HDF框架会尝试动态加载该驱动。 +> - 配置文件中preload字段配成0(DEVICE_PRELOAD_ENABLE),则系统启动过程中默认加载。 +> +> - 配成1(DEVICE_PRELOAD_ENABLE_STEP2),当系统支持快启的时候,则在系统完成之后再加载这一类驱动,否则和DEVICE_PRELOAD_ENABLE含义相同。 +> +> - 配成2(DEVICE_PRELOAD_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务(参考[消息机制](../driver/driver-hdf-message-management.md))时,如果驱动服务不存在,HDF框架会尝试动态加载该驱动。 > > - 按序加载(需要驱动为默认加载) +> > 配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级。不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高。 -- GitLab