driver-hdf-development.md 8.6 KB
Newer Older
W
wenjun 已提交
1 2
# 驱动开发<a name="ZH-CN_TOPIC_0000001051930361"></a>

N
NEEN 已提交
3 4 5
-   [驱动模型介绍](#section157425168112)
-   [驱动开发步骤](#section1969312275533)

W
wenjun 已提交
6 7
## 驱动模型介绍<a name="section157425168112"></a>

D
duangavin123 已提交
8
HDF框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个node,HDF驱动模型如下图所示:
W
wenjun 已提交
9

D
duangavin123 已提交
10
**图 1**  HDF驱动模型<a name="fig5487113011526"></a>  
W
wenjun 已提交
11 12


D
duangavin123 已提交
13
![](figure/zh-cn_image_0000001054564784.png)
W
wenjun 已提交
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

## 驱动开发步骤<a name="section1969312275533"></a>

基于HDF框架进行驱动的开发主要分为两个部分,驱动实现和驱动配置,详细开发流程如下所示:

1.  <a name="li35182436435"></a>驱动实现

    驱动实现包含驱动业务代码和驱动入口注册,具体写法如下:

    -   驱动业务代码

        ```
        #include "hdf_device_desc.h"  // HDF框架对驱动开放相关能力接口的头文件
        #include "hdf_log.h"          // HDF 框架提供的日志接口头文件
        
N
NEEN 已提交
29
        #define HDF_LOG_TAG "sample_driver"   // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签
W
wenjun 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
        
        //驱动对外提供的服务能力,将相关的服务接口绑定到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");
            return 0;
        }
        
        // 驱动资源释放的接口
        void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
        {
            HDF_LOGD("Sample driver release success");
            return;
        }
        ```

    -   驱动入口注册到HDF框架

        ```
        // 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量
        struct HdfDriverEntry g_sampleDriverEntry = {
            .moduleVersion = 1,
            .moduleName = "sample_driver",
            .Bind = HdfSampleDriverBind,
            .Init = HdfSampleDriverInit,
            .Release = HdfSampleDriverRelease,
        };
        
        // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
        HDF_INIT(g_sampleDriverEntry);
        ```

69

W
wenjun 已提交
70
2.  驱动编译
N
NEEN 已提交
71
    -   驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。
W
wenjun 已提交
72 73

        ```
D
duanxichao 已提交
74
        include $(LITEOSTOPDIR)/../../drivers/adapter/lite/khdf/lite.mk #导入hdf预定义内容,必需
W
wenjun 已提交
75 76 77 78 79 80 81
        MODULE_NAME :=    #生成的结果文件
        LOCAL_INCLUDE :=  #本驱动的头文件目录
        LOCAL_SRCS :=     #本驱动的源代码文件
        LOCAL_CFLAGS :=  #自定义的编译选项
        include $(HDF_DRIVER) #导入模板makefile完成编译
        ```

N
NEEN 已提交
82
    -   编译结果文件链接到内核镜像,添加到vendor目录下的hdf\_vendor.mk里面,示例如下:
W
wenjun 已提交
83 84 85 86 87 88

        ```
        LITEOS_BASELIB +=  -lxxx  #链接生成的静态库
        LIB_SUBDIRS    +=         #驱动代码Makefile的目录
        ```

89

W
wenjun 已提交
90 91
3.  驱动配置

D
duangavin123 已提交
92
    HDF使用HCS作为配置描述源码,HCS详细介绍参考[配置管理](driver-hdf-manage.md)介绍。
W
wenjun 已提交
93 94 95 96 97

    驱动配置包含两部分,HDF框架定义的驱动设备描述和驱动的私有配置信息,具体写法如下:

    -   驱动设备描述(必选)

N
NEEN 已提交
98
        HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device\_info.hcs配置文件中添加对应的设备描述,驱动的设备描述填写如下所示:
W
wenjun 已提交
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160

        ```
        root {
            device_info {
                match_attr = "hdf_manager";
                template host {       // host模板,继承该模板的节点(如下sample_host)如果使用模板中的默认值,则节点字段可以缺省
                    hostName = "";
                    priority = 100;
                    template device {
                        template deviceNode {
                            policy = 0;
                            priority = 100;
                            preload = 0;
                            permission = 0664;
                            moduleName = "";
                            serviceName = "";
                            deviceMatchAttr = "";
                        }
                    }
                }
                sample_host :: host{
                    hostName = "host0";    // host名称,host节点是用来存放某一类驱动的容器
                    priority = 100;        // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序
                    device_sample :: device {        // sample设备节点
                        device0 :: deviceNode {      // sample驱动的DeviceNode节点
                            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值相等
                        }
                    }
                }
            }
        }
        ```

    -   驱动私有配置信息(可选)

        如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init(参考[驱动开发](#li35182436435))传递给驱动,驱动的配置信息示例如下:

        ```
        root {
            SampleDriverConfig {
                sample_version = 1;
                sample_bus = "I2C_0";
                match_attr = "sample_config";   //该字段的值必须和device_info.hcs中的deviceMatchAttr值一致
            }
        }
        ```

        配置信息定义之后,需要将该配置文件添加到板级配置入口文件hdf.hcs(这一块可以通过OpenHarmony驱动子系统在DevEco集成驱动开发套件工具一键式配置,具体使用方法参考驱动开发套件中的介绍),示例如下:

        ```
        #include "device_info/device_info.hcs"
        #include "sample/sample_config.hcs"
        ```



D
duangavin123 已提交
161
>![](../public_sys-resources/icon-note.gif) **说明:** 
W
wenjun 已提交
162 163 164 165 166
>驱动加载方式支持按需加载和按序加载两种方式,具体使用方法如下:
>-   按需加载
>    ```
>    typedef enum {
>        DEVICE_PRELOAD_ENABLE = 0,
M
mamingshuai 已提交
167
>        DEVICE_PRELOAD_ENABLE_STEP2,
W
wenjun 已提交
168 169 170 171
>        DEVICE_PRELOAD_DISABLE,
>        DEVICE_PRELOAD_INVALID
>    } DevicePreload;
>    ```
D
duangavin123 已提交
172
>    配置文件中preload 字段配成 0 (DEVICE\_PRELOAD\_ENABLE ),则系统启动过程中默认加载;配成1(DEVICE\_PRELOAD\_ENABLE\_STEP2),当系统支持快启的时候,则在系统系统完成之后再加载这一类驱动,否则和DEVICE\_PRELOAD\_ENABLE 含义相同;配成2(DEVICE\_PRELOAD\_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务(参考[消息机制](driver-hdf-news.md))时,如果驱动服务不存在时,HDF框架会尝试动态加载该驱动。
W
wenjun 已提交
173 174 175
>-   按序加载(需要驱动为默认加载)
>    配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高。