OpenHarmony之HDF驱动开发流程指导

开发指导

场景介绍

关于驱动的开发我们主要目的是实现驱动代码的编写,但是驱动开发过程中需要服务管理、消息机制管理,才能使驱动在代码编译过程中进行加载。以下开发步骤中介绍了驱动开发、驱动消息机制管理开发、驱动服务管理开发的步骤。

驱动开发实例

基于HDF框架的驱动开发主要分为三个部分:驱动实现、驱动编译脚本编写和驱动配置。详细开发流程如下所示:

驱动实现

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

  • 驱动业务代码
#include "hdf_device_desc.h"          // HDF框架对驱动开发相关能力接口的头文件
#include "hdf_log.h"                  // HDF框架提供的日志接口头文件#define HDF_LOG_TAG sample_driver     // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签。// 将驱动对外提供的服务能力接口绑定到HDF框架。
int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
{HDF_LOGD("Sample driver bind success");return HDF_SUCCESS;
}// 驱动自身业务初始化的接口
int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
{HDF_LOGD("Sample driver Init success");return HDF_SUCCESS;
}// 驱动资源释放的接口
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);

驱动编译脚本编写

  • LiteOS
  • 涉及Makefile和BUILD.gn修改:
    • Makefile部分:
    • 驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。
      include $(LITEOSTOPDIR)/../../drivers/hdf_core/adapter/khdf/liteos/lite.mk # 【必需】导入hdf预定义内容
      MODULE_NAME :=        #生成的结果文件
      LOCAL_INCLUDE :=      #本驱动的头文件目录
      LOCAL_SRCS :=         #本驱动的源代码文件
      LOCAL_CFLAGS :=      #自定义的编译选项
      include $(HDF_DRIVER) #导入Makefile模板完成编译

      编译结果文件链接到内核镜像,添加到drivers/hdf_core/adapter/khdf/liteos目录下的hdf_lite.mk里面,示例如下:

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

      BUILD.gn部分:

      添加模块BUILD.gn,可参考如下示例:

      import("//build/lite/config/component/lite_component.gni")
      import("//drivers/hdf_core/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/hdf_core/adapter/khdf/liteos/BUILD.gn**里面:

      group("liteos") {public_deps = [ ":$module_name" ]deps = ["xxx/xxx",#新增模块BUILD.gn所在的目录,/drivers/hdf_core/adapter/khdf/liteos]
      }

      Linux

      如果需要定义模块控制宏,需要在模块目录xxx里面添加Kconfig文件,并把Kconfig文件路径添加到drivers/hdf_core/adapter/khdf/linux/Kconfig里面:

      source "drivers/hdf/khdf/xxx/Kconfig" #目录为hdf模块软链接到kernel里面的目录

      添加模块目录到drivers/hdf_core/adapter/khdf/linux/Makefile

      obj-$(CONFIG_DRIVERS_HDF)  += xxx/

      在模块目录xxx里面添加Makefile文件,在Makefile文件里面添加模块代码编译规则:

      obj-y  += xxx.o

      驱动配置

      HDF使用HCS作为配置描述源码,HCS详细介绍配置管理。

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

    • 驱动设备描述(必选)
    • HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描述。驱动的设备描述填写如下所示:
      root {device_info {match_attr = "hdf_manager";template host {       // host模板,继承该模板的节点(如下sample_host)如果使用模板中的默认值,则节点字段可以缺省。hostName = "";priority = 100;uid = "";         // 用户态进程uid,缺省为空,会被配置为hostName的定义值,即普通用户。gid = "";         // 用户态进程gid,缺省为空,会被配置为hostName的定义值,即普通用户组。caps = [""];      // 用户态进程Linux capabilities配置,缺省为空,需要业务模块按照业务需要进行配置。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的加载顺序。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;             // 驱动按需加载字段。permission = 0664;       // 驱动创建设备节点权限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权限时,请找安全专家进行评审。
    • 驱动私有配置信息(可选)

      如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息。HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject中的property里面,驱动的配置信息示例如下:

    • 进程的uid在文件base/startup/init/services/etc/passwd中配置,进程的gid在文件base/startup/init/services/etc/group中配置,进程uid和gid配置参考:系统服务用户组添加方法。
    • caps值:格式为caps = ["xxx"],如果要配置CAP_DAC_OVERRIDE,此处需要填写caps = ["DAC_OVERRIDE"],不能填写为caps = ["CAP_DAC_OVERRIDE"]。
    • preload:驱动按需加载字段。
      root {SampleDriverConfig {sample_version = 1;sample_bus = "I2C_0";match_attr = "sample_config";   // 该字段的值必须和device_info.hcs中的deviceMatchAttr值一致}
      }

      配置信息定义之后,需要将该配置文件添加到板级配置入口文件hdf.hcs,示例如下:

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

      想学习更多华为鸿蒙HarmonyOS开发知识,在这里我为大家准备了华为鸿蒙HarmonyOS开发者资料大全,大家可以自行点击链接领取:《做鸿蒙应用开发到底学习些啥?》

      其次就是考虑到市场上还没有系统性的学习资料,同时我也整理了一份《鸿蒙 (Harmony OS)开发学习手册》特意整理成PDF文档方式,分享给大家参考学习,大家可以根据自身情况进行获取:《鸿蒙开发学习指南》

      《鸿蒙 (Harmony OS)开发学习手册》

      一、入门必看

      1. 应用开发导读(ArkTS)

      2. 应用开发导读(Java)

      3.......

      二、HarmonyOS 概念

      1. 系统定义

      2. 技术架构

      3. 技术特性

      4. 系统安全

      5......

      三、如何快速入门?《鸿蒙基础入门开发宝典!》

      1. 基本概念

      2. 构建第一个ArkTS应用

      3. 构建第一个JS应用

      4. ……

      四、开发基础知识

      1. 应用基础知识

      2. 配置文件

      3. 应用数据管理

      4. 应用安全管理

      5. 应用隐私保护

      6. 三方应用调用管控机制

      7. 资源分类与访问

      8. 学习ArkTS语言

      9. ……

      五、基于ArkTS 开发

      1. Ability开发

      2. UI开发

      3. 公共事件与通知

      4. 窗口管理

      5. 媒体

      6. 安全

      7. 网络与链接

      8. 电话服务

      9. 数据管理

      10. 后台任务(Background Task)管理

      11. 设备管理

      12. 设备使用信息统计

      13. DFX

      14. 国际化开发

      15. 折叠屏系列

      16. ……

      更多了解更多鸿蒙开发的相关知识可以参考:《做鸿蒙应用开发到底学习些啥?》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/627382.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

henauOJ 1104: 单词数

题目描述 lily的好朋友xiaoou333最近很空,他想了一件没有什么意义的事情,就是统计一篇文章的单词总数。下面你的任务是帮助xiaoou333解决这个问题。 输入 有多组数据,每组一行,每组就是一篇小文章。每篇小文章都是由小写字母和…

spring boot mybatis-plus dynamic-datasource 配置文件 相关依赖环境配置

spring boot mybatis-plus dynamic-datasource 配置文件 相关依赖环境配置 ##yaml配置 server:port: 8866servlet:context-path: /yymtomcat:max-threads: 300connection-timeout: 57000max-connections: 500connection-timeout: 57000 spring:datasource:dynamic:primary: m…

二叉树遍历C++

假设二叉树上各结点的权值互不相同且都为正整数。 给定二叉树的后序遍历和中序遍历,请你输出二叉树的前序遍历的最后一个数字。 输入格式 第一行包含整数 N,表示二叉树结点总数。 第二行给出二叉树的后序遍历序列。 第三行给出二叉树的中序遍历序列。 …

【IPC通信--共享内存mmap】

共享内存是一种高效的进程间通信方式,可以在多个进程之间共享数据,提高程序的效率。mmap是一种常用的实现共享内存的机制,它可以将一个文件或者设备映射到内存中,使得多个进程可以通过访问这块内存来实现数据共享。 一、共享内存…

SpringBoot 源码解析4:refresh 方法解析

SpringBoot 源码解析4:refresh 方法解析 1. refresh 方法解析2. 准备刷新 AbstractApplicationContext#prepareRefresh3. 获取bean工厂 AbstractApplicationContext#obtainFreshBeanFactory4. 准备bean工厂 AbstractApplicationContext#prepareBeanFactory5. Servle…

Java学习,一文掌握Java之SpringBoot框架学习文集(6)

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。 🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。 🎉欢迎 👍点赞✍评论…

1、docker常用操作

docker常用操作 1、启动docker2.容器2.1创建容器2.2查看容器2.3启动容器 3、镜像3.1查看镜像3.2创建镜像 4、在宿主机和容器之间交换⽂件5、docker 容器之间通信5.1查看网络5.2创建网络5.3容器连接到网络5.4网络端口映射5.5Docker的跨主机网络访问 1、启动docker 参考&#xf…

Linux 修改文件名称的三种方法

修改文件名称是 Linux 系统中常见的操作之一。有三种方法可以修改文件名称: 1. 使用 mv 命令 mv 命令是用于移动或重命名文件的命令。要使用 mv 命令重命名文件,请使用以下语法: mv old_file_name new_file_name 例如,要将文件…

阿里国际站运营每天具体做什么工作?附运营方法!

相信很多刚接触阿里国际站的运营人员都会迷茫,没有思路还容易产生焦虑,主要就是担心运营没效果!今天大白就带着大家一起揭秘阿里国际站运营每天必做的事情都有哪些,带你更好地了解阿里国际站应该如何运营! 阿里国际站运…

5.【CPP】内存管理(text段data段bss段||nwedelete底层实现||源码)

一.内存管理 1.如图 2.heap下面的空间 应用程序加载到内存中由操作系统完成对bss,data,text,stack加载,并在内存分配空间。在编译阶段已经确定分配了多少空间,属于静态分配。 而malloc等在程序运行时在堆上开辟空间则属于动态分配,需要手动f…

k8s---配置资源管理

内容预知 目录 内容预知 secret资源配置 secert的几种模式 pod如何来引用secret 陈述式创建secret 声明式base64编码配置secret 将secret用vlumes的方式挂载到pod中 传参的方式将环境变量导入pod 如何通过secret加密方式获取仓库密码 configmap的资源配置 陈述式创建…

ubuntu 22 搭建git服务

第一步,安装git: sudo apt-get install git 创建用户信息 git config --global user.name soft 第二步,创建一个git用户,用来运行git服务: sudo adduser git 创建git仓库的存储目录、更改文件目录属主为代码仓库…

2.3数据链路层02

2.3 数据链路层 2.3.5 以太网 1、以太网概念 以太网是一种计算机局域网技术。IEEE(电气与电子工程师协会:Institute of Electrical and Electronics Engineers)组织的IEEE802.3标准制定了以太网的技术标准,它规定了包括物理层的…

Gartner发布CPS安全2024年预测:安全形势动荡的四大向量

随着威胁形势、自动化和人工智能采用的步伐以及供应商形势不断快速发展,我们为安全和风险管理领导者提供了四项预测,以规划 2024 年及以后 CPS 安全的未来发展方向。 主要发现 随着人工智能的采用加速增加网络物理系统( CPS)的“智…

openssl3.2 - 官方demo学习 - cms - cms_comp.c

文章目录 openssl3.2 - 官方demo学习 - cms - cms_comp.c概述笔记END openssl3.2 - 官方demo学习 - cms - cms_comp.c 概述 CMS is Cryptographic Message Syntax (CMS) standard 用CMS操作, 将明文压缩 默认编译出来的openssl3.2没有zlib库, 需要添加zlib特性[openssl3.2 - …

JAVA基础---内部类详解

文章目录 1. 内部类概念2. 内部类的分类2.1 内部类2.1.1 实例内部类2.1.2 静态内部类2.2 局部内部类2.3 匿名内部类 1. 内部类概念 当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务&#xff0c…

MPLS基础架构

目录 一、MPLS多协议标签交换概述 1、MPLS是什么 2、MPLS-VPN 3、MPLS起源 (1)、MPLS解决的问题 MPLS解决了三层转发短板问题。 (2)、交换机转发流程 (3)、路由器转发流程 (4)、交换…

【程序员的自我修养11】栈与函数调用过程

绪论 大家好,欢迎来到【程序员的自我修养】专栏。正如其专栏名,本专栏主要分享学习《程序员的自我修养——链接、装载与库》的知识点以及结合自己的工作经验以及思考。编译原理相关知识本身就比较有难度,我会尽自己最大的努力,争…

gradle版本中-bin与-all区别

打开android studio下载的gradle文件,发现-all比-bin多了一个docs文件夹和一个src文件夹。-bin是编译后的二进制发布版,-all还包含了源码和文档,比-bin大了几十兆,两者其余没有区别。 android开发只关注gradle功能不关注实现的情况…

android studio报错:Connect to maven.google.com:443 [mavaen.google.com/

报错很干脆,办法也很干脆。 直接替换 将【https://maven.google.com】替换 为:【http://maven.aliyun.com/nexus/content/groups/public】 或者替换 为:【https://dl.google.com/dl/android/maven2/】