Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
0546ba86
D
Docs
项目概览
OpenHarmony
/
Docs
大约 2 年 前同步成功
通知
161
Star
293
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
0546ba86
编写于
7月 07, 2022
作者:
L
liyan
提交者:
Gitee
7月 07, 2022
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
规范性检查
Signed-off-by:
N
li-yan339
<
liyan339@h-partners.com
>
上级
1f1cdaca
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
105 addition
and
97 deletion
+105
-97
zh-cn/device-dev/driver/driver-hdf-development.md
zh-cn/device-dev/driver/driver-hdf-development.md
+105
-97
未找到文件。
zh-cn/device-dev/driver/driver-hdf-development.md
浏览文件 @
0546ba86
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
## 驱动模型介绍
## 驱动模型介绍
HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个
host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个n
ode。HDF驱动模型如下图所示:
HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个
Host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个N
ode。HDF驱动模型如下图所示:
**图1**
HDF驱动模型
**图1**
HDF驱动模型
...
@@ -12,28 +12,28 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心
...
@@ -12,28 +12,28 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心
## 驱动开发步骤
## 驱动开发步骤
基于HDF框架
进行驱动的开发主要分为两个部分,驱动实现
和驱动配置。详细开发流程如下所示:
基于HDF框架
的驱动开发主要分为三个部分:驱动实现、驱动编译
和驱动配置。详细开发流程如下所示:
1.
驱动实现
1.
驱动实现
驱动实现包含驱动业务代码和驱动入口注册,具体写法如下:
驱动实现包含驱动业务代码
实现
和驱动入口注册,具体写法如下:
-
驱动业务代码
-
驱动业务代码
```
```
#include "hdf_device_desc.h" // HDF框架对驱动开发相关能力接口的头文件
#include "hdf_device_desc.h"
// HDF框架对驱动开发相关能力接口的头文件
#include "hdf_log.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)
int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
{
{
HDF_LOGD("Sample driver bind success");
HDF_LOGD("Sample driver bind success");
return 0;
return 0;
}
}
// 驱动自身业务初始的接口
// 驱动自身业务初始
化
的接口
int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
{
{
HDF_LOGD("Sample driver Init success");
HDF_LOGD("Sample driver Init success");
...
@@ -50,7 +50,7 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心
...
@@ -50,7 +50,7 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心
-
驱动入口注册到HDF框架
-
驱动入口注册到HDF框架
```
```
// 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量
// 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量
。
struct HdfDriverEntry g_sampleDriverEntry = {
struct HdfDriverEntry g_sampleDriverEntry = {
.moduleVersion = 1,
.moduleVersion = 1,
.moduleName = "sample_driver",
.moduleName = "sample_driver",
...
@@ -59,93 +59,94 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心
...
@@ -59,93 +59,94 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心
.Release = HdfSampleDriverRelease,
.Release = HdfSampleDriverRelease,
};
};
// 调用HDF_INIT将驱动入口注册到HDF框架中
,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出
// 调用HDF_INIT将驱动入口注册到HDF框架中
。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动;当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
HDF_INIT(g_sampleDriverEntry);
HDF_INIT(g_sampleDriverEntry);
```
```
2.
驱动编译
2.
驱动编译
-
liteos
涉及makefile和BUILD.gn修改:
-
LiteOS
- makefile部分
:
涉及Makefile和BUILD.gn修改
:
驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。
- Makefile部分:
驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。
```
include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk #导入hdf预定义内容,必需
MODULE_NAME := #生成的结果文件
```
LOCAL_INCLUDE := #本驱动的头文件目录
include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk # 【必需】导入hdf预定义内容
LOCAL_SRCS := #本驱动的源代码文件
MODULE_NAME := #生成的结果文件
LOCAL_CFLAGS := #自定义的编译选项
LOCAL_INCLUDE := #本驱动的头文件目录
include $(HDF_DRIVER) #导入Makefile模板完成编译
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 #链接生成的静态库
LITEOS_BASELIB += -lxxx #链接生成的静态库
LIB_SUBDIRS += #驱动代码Makefile的目录
LIB_SUBDIRS += #驱动代码Makefile的目录
```
```
- BUILD.gn部分:
- BUILD.gn部分:
添加模块BUILD.gn参考定义如下内容:
添加模块BUILD.gn参考定义如下内容:
```
```
import("//build/lite/config/component/lite_component.gni")
import("//build/lite/config/component/lite_component.gni")
import("//drivers/adapter/khdf/liteos/hdf.gni")
import("//drivers/adapter/khdf/liteos/hdf.gni")
module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
module_name = "xxx"
module_name = "xxx"
hdf_driver(module_name) {
hdf_driver(module_name) {
sources = [
sources = [
"xxx/xxx/xxx.c",
#模块要编译的源码文件
"xxx/xxx/xxx.c",
#模块要编译的源码文件
]
]
public_configs = [ ":public" ] #使用依赖的头文件配置
public_configs = [ ":public" ] #使用依赖的头文件配置
}
}
config("public") {
#定义依赖的头文件配置
config("public") {
#定义依赖的头文件配置
include_dirs = [
include_dirs = [
"xxx/xxx/xxx",
#依赖的头文件目录
"xxx/xxx/xxx",
#依赖的头文件目录
]
]
}
}
```
```
把新增模块的BUILD.gn所在的目录添加到/drivers/adapter/khdf/liteos/BUILD.gn
里面:
把新增模块的BUILD.gn所在的目录添加到**/drivers/adapter/khdf/liteos/BUILD.gn**
里面:
```
```
group("liteos") {
group("liteos") {
public_deps = [ ":$module_name" ]
public_deps = [ ":$module_name" ]
deps = [
deps = [
"xxx/xxx", #新增模块BUILD.gn所在的目录,目录结构相对于/drivers/adapter/khdf/liteos
"xxx/xxx", #新增模块BUILD.gn所在的目录,目录结构相对于/drivers/adapter/khdf/liteos
]
]
}
}
```
```
-
l
inux
-
L
inux
如果需要定义模块控制宏,需要在模块目录xxx里面添加Kconfig文件,并把Kconfig文件路径添加到drivers/adapter/khdf/linux/Kconfig
里面:
如果需要定义模块控制宏,需要在模块目录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.
驱动配置
3.
驱动配置
...
@@ -155,19 +156,19 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心
...
@@ -155,19 +156,19 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心
-
驱动设备描述(必选)
-
驱动设备描述(必选)
HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描述
,
驱动的设备描述填写如下所示:
HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描述
。
驱动的设备描述填写如下所示:
```
```
root {
root {
device_info {
device_info {
match_attr = "hdf_manager";
match_attr = "hdf_manager";
template host { // host模板,继承该模板的节点(如下sample_host)如果使用模板中的默认值,则节点字段可以缺省
template host { // host模板,继承该模板的节点(如下sample_host)如果使用模板中的默认值,则节点字段可以缺省
。
hostName = "";
hostName = "";
priority = 100;
priority = 100;
uid = "";
// 用户态进程uid,缺省为空,会被配置为hostName的定义值,即普通用户
uid = "";
// 用户态进程uid,缺省为空,会被配置为hostName的定义值,即普通用户。
gid = "";
// 用户态进程gid,缺省为空,会被配置为hostName的定义值,即普通用户组
gid = "";
// 用户态进程gid,缺省为空,会被配置为hostName的定义值,即普通用户组。
caps = [""];
// 用户态进程Linux capabilities配置,缺省为空,需要业务模块按照业务需要进行配置
caps = [""];
// 用户态进程Linux capabilities配置,缺省为空,需要业务模块按照业务需要进行配置。
template device {
template device {
template deviceNode {
template deviceNode {
policy = 0;
policy = 0;
...
@@ -181,39 +182,41 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心
...
@@ -181,39 +182,41 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心
}
}
}
}
sample_host :: host{
sample_host :: host{
hostName = "host0"; // host名称,host节点是用来存放某一类驱动的容器
hostName = "host0"; // host名称,host节点是用来存放某一类驱动的容器
。
priority = 100; // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序
priority = 100; // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序
。
caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; // 用户态进程Linux capabilities配置
caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; // 用户态进程Linux capabilities配置
。
device_sample :: device { // sample设备节点
device_sample :: device { // sample设备节点
device0 :: deviceNode { // sample驱动的DeviceNode节点
device0 :: deviceNode { // sample驱动的DeviceNode节点
policy = 1; // policy字段是驱动服务发布的策略,在驱动服务管理章节有详细介绍
policy = 1; // policy字段是驱动服务发布的策略,在驱动服务管理章节有详细介绍
。
priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序
priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序
。
preload = 0; // 驱动按需加载字段,在本章节最后的说明有详细介绍
preload = 0; // 驱动按需加载字段,在本章节最后的说明有详细介绍
。
permission = 0664; // 驱动创建设备节点权限
permission = 0664; // 驱动创建设备节点权限
moduleName = "sample_driver";
// 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
moduleName = "sample_driver";
// 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致。
serviceName = "sample_service"; // 驱动对外发布服务的名称,必须唯一
serviceName = "sample_service"; // 驱动对外发布服务的名称,必须唯一
。
deviceMatchAttr = "sample_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
deviceMatchAttr = "sample_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
。
}
}
}
}
}
}
}
}
}
}
```
```
说明:
>  **说明:**<br>
uid、gid、caps等配置项是用户态驱动的启动配置,内核态不用配置。
>
> - uid、gid、caps等配置项是用户态驱动的启动配置,内核态不用配置。
根据进程权限最小化设计原则,业务模块uid、gid不用配置,如上面的sample_host,使用普通用户权限,即uid和gid被定义为hostName的定义值。
>
> - 根据进程权限最小化设计原则,业务模块uid、gid不用配置,如上面的sample_host,使用普通用户权限,即uid和gid被定义为hostName的定义值。
如果普通用户权限不能满足业务要求,需要把uid、gid定义为system或者root权限时,请找安全专家进行评审。
>
> - 如果普通用户权限不能满足业务要求,需要把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)。
>
> - 进程的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)框架以组件化的驱动模型作为核心
...
@@ -249,7 +252,12 @@ HDF(Hardware Driver Foundation)框架以组件化的驱动模型作为核心
> } DevicePreload;
> } 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值越小,加载优先级越高。
> 配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级。不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录