OpenHarmony-HDF驱动框架介绍及加载过程分析

前言

HarmonyOS面向万物互联时代,而万物互联涉及到了大量的硬件设备,这些硬件的离散度很高,它们的性能差异与配置差异都很大,所以这要求使用一个更灵活、功能更强大、能耗更低的驱动框架。OpenHarmony系统HDF驱动框架采用C语言面向对象编程模型构建,通过平台解耦、内核解耦,来达到兼容不同内核,统一平台底座的目的,从而帮助开发者实现驱动一次开发,多系统部署的效果。

1.HDF 驱动框架

OpenHarmony 系统 HDF 驱动框架主要由驱动基础框架、驱动程序、驱动配置文件和驱动接口这四个部分组成。
1)HDF 驱动基础框架提供统一的硬件资源管理,驱动加载管理以及设备节点管理等功能。驱动框架采用的是主从模式设计,由 Device Manager 和 Device Host 组成。Device Manager 提供了统一的驱动管理,Device Manager 启动时根据 Device Information 提供驱动设备信息加载相应的驱动 Device Host,并控制 Host 完成驱动的加载。Device Host 提供驱动运行的环境,同时预置 Host Framework 与 Device Manager 进行协同,完成驱动加载和调用。根据业务的需求 Device Host 可以有多个实例。
2)驱动程序实现驱动具体的功能,每个驱动由一个或者多个驱动程序组成,每个驱动程序都对应着一个 Driver Entry。Driver Entry 主要完成驱动的初始化和驱动接口绑定功能。
3)驱动配置文件.hcs 主要由设备信息(Device Information)和设备资源(Device Resource)组成。Device Information 完成设备信息的配置。如配置接口发布策略,驱动加载的方式等。Device Resource 完成设备资源的配置。如 GPIO 管脚、寄存器等资源信息的配置。
4)驱动接口 HDI(Hardware Driver interface )提供标准化的接口定义和实现,驱动框架提供 IO Service和IO Dispatcher 机制,使得不同部署形态下驱动接口趋于形式一致。

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

2.HDF 驱动开发

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

2.1 驱动实现

驱动实现包含驱动业务代码和驱动入口注册。

2.1.1 驱动业务代码

//驱动对外提供的服务能力,将相关的服务接口绑定到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;  
}

2.1.2驱动入口注册到HDF框架

// 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量

struct HdfDriverEntry g_sampleDriverEntry =
 {  
	.moduleVersion = 1, 
	.moduleName = "sample_driver",  
	.Bind = HdfSampleDriverBind,  
	.Init = HdfSampleDriverInit, 
	.Release = HdfSampleDriverRelease,
};

HDF_INIT(g_sampleDriverEntry);
// 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。

2.2 驱动配置

驱动配置包含两部分,HDF框架定义的驱动设备描述和驱动的私有配置信息。HDF使用HCS作为配置描述源码,内容以 Key-Value 键值对为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。HC-GEN (全称 HDF Configuration Generator) 是 HCS 配置转换工具,可以将 HDF 配置文件转换为软件可读取的文件格式:在弱性能环境中,转换为配置树源码,驱动可直接调用 C代码获取配置;在高性能环境中,转换为 HCB(HDF Configuration Binary)二进制文件,驱动可使用 HDF框架提供的配置解析接口获取配置。
HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。驱动配置过程的原理图如下所示:

2.2.1 驱动设备描述(必选)

HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描述,驱动的设备描述填写如下所示:

sample_host :: host{
	hostName = "host0"; //host名称,host节点是用来存放某一类驱动的容器。
	priority = 100; //host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序。
	device_sample :: device { //sample设备节点。
		device0 :: deviceNode { //sample驱动的DeviceNode节点。
		policy = 1; //驱动服务发布的策略
		priority = 100; //驱动启动优先级(0-200),值越大优先级越低,建议默认配 100,优先级相同则不保证 device 的加载顺序
		preload = 0; //驱动按需加载字段
		permission = 0664;//驱动创建设备节点权限
		moduleName = "sample_driver"; //驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
		serviceName = "sample_service"; //驱动对外发布服务的名称,必须唯一
		deviceMatchAttr = "sample_config";//驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等。
		}
	}
}

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

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

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

3.HDF 驱动加载

HDF驱动加载包括按需加载和按序加载。按需加载是HDF框架支持驱动在系统启动过程中默认加载,或者在系统启动之后动态加载;按序加载是HDF框架支持驱动在系统启动的过程中按照驱动的优先级进行加载。HDF框架定义的驱动按需加载方式的策略是由配置文件中的 preload 字段来控制,preload 字段的取值范围以及含义如下:

驱动的按序加载是通过配置文件中的 priority(取值范围为整数 0 到 200)来决定的,priority 值越小,表示的优先级越高。驱动的加载顺序,优先根据 host 的 priority 决定,如果host 的 priority 相同,再根据 host 内的驱动 priority 值来决定加载顺序。

3.1 HDF_INIT宏展开

驱动入口注册到HDF框架,会调用HDF_INIT函数将驱动入口地址注册到HDF框架。
#define HDF_SECTION__attribute__((section(“.hdf.driver”)))
#define HDF_DRIVER_INIT(module)
const size_t USED_ATTR module##HdfEntry HDF_SECTION = (size_t)(&(module))

可以看到 HDF_INIT 宏是定义了一个“驱动模块名+HdfEntry”的符号放到".hdf.driver"所在 section,该符号指向的内存地址即为驱动程序入口结构体的地址。这个特殊的 section 将用于开机启动时查找设备驱动。

3.2获取驱动列表

HDF驱动框架通过将驱动程序入口符号的地址集中存放到一个特殊的 section 来实现对驱动的索引,这个section的开头和末尾插入了_hdf_drivers_start、_hdf_drivers_end两个特殊符号,用于标记这个 section 的范围,两个特殊符号之间的数据即为驱动实现指针。

3.3获取设备列表

配置文本编译后会变成二进制格式的配置文件,其中设备相关信息被存放在一个用“hdf_manager”标记的 device_info 配置块中,host的内容以块的形式在device_info 块中依次排列,host块中记录了host名称、启动优先级和设备列表信息。设备信息中的 moduleName字段将用于和驱动程序入口中的moduleName进行匹配,从而为设备匹配到正确的驱动程序,完成设备与驱动的匹配,具体流程图如下:

3.4驱动框架启动

late_initcall宏展开

__define_initcall宏展开

___define_initcall宏展开

宏含义:
1)声明一个类型为initcall_t,名称为__initcall_DeviceManagerInit的函数指针
2)将这个函数指针初始化为DeviceManagerInit
3)编译的时候需要把这个函数指针变量放置到名称为“.initcall7.init”的section中,其实质就是将这个函数DeviceManagerInit的首地址放置到了这个.initcall7.init的section中

内核初始化的内存图:

其中__init用来标示的是初始化函数,在初始化后不会再调用,__initdata是初始化数据,__initparam是初始化参数,其他7个初始化宏就是初始化函数会用到的,初始化的时候按
照.initcall1.init->.initcall7.init的顺序初始化。do_basic_setup执行.initcall1.init->.initcall7.init的顺序初始化。

4总结

1)在系统启动时,DeviceManagerInit通过late_initcall先启动。
2) Device Manager 根据 Device Information 信息,解析配置文件中的 Host 列表,根据 Host 列表中的信息来实例化对应的 Host 对象。
3)Host遍历设备列表去获取与之匹配的驱动程序名称,然后基于驱动程序名称遍历.hdf.driver section 获得驱动程序地址。
4)设备与驱动匹配成功之后,获取指定驱动的入口地址,加载对应的设备驱动程序。
5)调用指定驱动的 Bind 接口,用于关联设备和服务实例。
6)调用指定驱动的 Init 接口,用于完成驱动的相关初始化工作。
7)如果驱动被卸载或者因为硬件等原因 Init 接口返回失败,Release 将被调用,用于释放驱动申请的各类资源。

如果大家想更加深入的学习 OpenHarmony(鸿蒙南向) 开发的全栈内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……

系统架构分析:https://qr18.cn/CgxrRy

  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:https://qr21.cn/FV7h05

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UE5近战对抗系统Tutorial

文章目录 BP_Character 组合攻击Notify State 检测攻击BP_Character 攻击反馈BP_Character 生命系统BP_Character 死亡效果BP_Character 武器系统BP_Enemy 初始化和行为树 BP_Character 组合攻击 首先我们获取攻击动画,在这里使用的是 Easy Combo Buffering 的攻击…

Nature推荐:快速完成一篇论文,你只需要这 12 个技巧!

我是娜姐 迪娜学姐 ,一个SCI医学期刊编辑,探索用AI工具提效论文写作和发表。 当你面对空白屏幕,苦思冥想数小时、数日甚至数月后,仍然没办法搞定论文。你该怎么办? 写作障碍虽然普遍存在,但对需要发表论文…

PyMuPDF 操作手册 - 05 PDF的OCR识别等

文章目录 六、PyMuPDF的OCR识别6.1 使用 Tesseract进行OCR6.2 使用MuPDF进行OCR6.3 使用 Python 包easyocr进行OCR识别6.4 使用 Python ocrmypdf包进行OCR识别6.5 将图像批量OCR并转换为PDF七、PDF附加、嵌入、批注等7.1 附加文件7.2 嵌入文件7.3 从文档中获取所有批注六、PyMu…

如何恢复未格式化分区数据?看这里!

什么是未格式化分区? 未格式化或RAW文件系统的分区无法被Windows操作系统识别和挂载,因此,Windows会提示你进行格式化以创建新的文件系统。注意,不要进行格式化。通常,文件系统变为未格式化或RAW会出现以下常见错误消…

又发现一款独立清理神器,界面清爽,功能强大,没有广告!

360清理Pro独立提取版是360公司推出的一款清理软件,主要用于清理系统垃圾和优化系统性能,涵盖了四大类型的清理场景,分别为:微信、QQ的垃圾扫描及清理,系统盘中的大文件、重复文件扫描及清理以及系统软件使用痕迹的清理…

Docker 可用镜像源

当使用 docker 发现拉取不到镜像时,可以编辑 /etc/docker/daemon.json 文件,添加如下内容: 这文章不涉及政治,不涉及敏感信息,三番五次的审核不通过,一删再删,只好换图片了。 重新加载服务配置…

视频监控平台功能介绍:内部设备管理(rtsp、sdk、onvif、ehome/ISUP、主动注册协议等)

一、功能概述 AS-V1000视频平台是一套集成了用户设备权限管理、视音频监控、大容量存储、电子地图的系统平台软件。它结合了现代视频技术、网络通讯技术、计算机控制技术、流媒体传输技术的综合解决方案,为用户提供了强大的、灵活的组网和应用能力。 AS-V1000管理端…

HarmonyOS 开发知识:一个基于 emitter 封装了一个便捷的 EventBus 事件通知

引言 鸿蒙提供提供了在同一进程不同线程间,或同一进程同一线程内,发送和处理事件的能力,包括持续订阅事件、单次订阅事件、取消订阅事件,以及发送事件到事件队列的能力。 ohos.events.emitter Emitter 封装前使用:e…

笔记-python飞机大战

python版的飞机大战,有兴趣的可以看下。 父类是飞行物类是所有对象的父类,setting里面是需要加载的图片,你可以换称自己的喜欢的图片,敌机可以分为敌机和奖励,enemy为普通敌人的父类,award为奖励敌机的父类…

鸿蒙正在跨越“生态繁荣阈值”

作者 | 曾响铃 文 | 响铃说 先讲一个故事。 一个朋友曾经做了一个本地互联网装修平台,一边是装修服务的提供者——各工种工人等,一边是有装修需求的业主。这个平台要做独立生态,绕过旧有的装修公司渠道垄断,直接提供服务&#…

凯迪仕霸榜全渠道TOP1 全域曝光100亿

618年中狂欢盛典,已正式落下帷幕。智能锁行业领头羊凯迪仕,凭借过硬的科技产品力和品牌势能,在全域流量加持以及传奇大师K70新品强势曝光之下,霸榜天猫、京东、抖音各平台,稳居各类型榜单榜首,继续以行业领…

Redis-事务-基本操作-在执行阶段出错不会回滚

文章目录 1、Redis事务控制命令2、Redis事务错误处理3、Redis事务错误处理,在执行阶段出错不会回滚 1、Redis事务控制命令 127.0.0.1:6379> keys * (empty array) 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> set a1 v1 QUEUED 127.0.0.1:6379(TX)>…

华为---配置OSPF的认证(三)

9.3 配置OSPF的认证 9.3.1 原理概述 OSPF支持报文验证功能,只有通过验证的报文才能接收,否则将不能正常建立邻居关系。OSPF协议支持两种认证方式——区域认证和链路认证。使用区域认证时,一个区域中所有的路由器在该区域下的认证模式和口令…

韩顺平0基础学java——第28天

p569-591 坦克大战!(绘图监听事件线程文件处理) 绘图 绘图原理 Component类提供了两个和绘图相关最重要的方法: 1. paint(Graphics g)绘制组件的外观 2. repaint()刷新组件的外观。 当组件第一次在屏幕显示的时候,程序会自动的调用paint()…

容器之按钮盒构件演示

代码; #include <gtk-2.0/gtk/gtk.h> #include <glib-2.0/glib.h> #include <gtk-2.0/gdk/gdkkeysyms.h> #include <stdio.h>int main(int argc, char *argv[]) {gtk_init(&argc, &argv);GtkWidget *window;window gtk_window_new(GTK_WINDO…

北大推出全新机器人多模态大模型!面向通用和机器人场景的高效推理和操作

为了赋予机器人端到端的推理和操纵能力&#xff0c;本文创新性地将视觉编码器与高效的状态空间语言模型集成&#xff0c;构建了全新的 RoboMamba 多模态大模型&#xff0c;使其具备视觉常识任务和机器人相关任务的推理能力&#xff0c;并都取得了先进的性能表现。同时&#xff…

【秋招刷题打卡】Day01-自定义排序

Day01-自定排序 前言 给大家推荐一下咱们的 陪伴打卡小屋 知识星球啦&#xff0c;详细介绍 >笔试刷题陪伴小屋-打卡赢价值丰厚奖励 < ⏰小屋将在每日上午发放打卡题目&#xff0c;包括&#xff1a; 一道该算法的模版题 (主要以力扣&#xff0c;牛客&#xff0c;acwin…

20240621在飞凌的OK3588-C开发板的Buildroot系统中集成i2ctool工具

20240621在飞凌的OK3588-C开发板中打开i2ctool工具 2024/6/21 17:44 默认继承的i2c工具&#xff1a; rootrk3588-buildroot:/# rootrk3588-buildroot:/# i2c i2c-stub-from-dump i2cdump i2cset i2cdetect i2cget i2ctransfer rootrk3588-…

CVPR 2024盛况空前,上海科技大学夺得最佳学生论文奖,惊艳全场

CVPR 2024盛况空前&#xff01;上海科技大学夺得最佳学生论文奖&#xff0c;惊艳全场&#xff01; 会议之眼 快讯 2024 年 CVPR &#xff08;Computer Vision and Pattern Recogntion Conference) 即国际计算机视觉与模式识别会议&#xff0c;于6月17日至21日正在美国西雅图召…

邀请函 | 桥田智能出席AMTS展会 家族新成员正式发布

作为国际汽车制造技术与装备及材料专业展览会&#xff0c;AMTS将于2024年7月3-5日在上海新国际博览中心举行。本届展会以【向“新”而行 “智”领未来】为主题&#xff0c;聚焦汽车及新能源全产业链&#xff0c;围绕“车身工程、部件工程、新能源三电工程及未来汽车开发”等技…