0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

OpenHarmony系统HDF驱动框架概述

HarmonyOS开发者 来源:HarmonyOS开发者 作者:HarmonyOS 2021-09-03 09:29 次阅读

OpenHarmony系统HDF驱动框架概述

OpenAtom OpenHarmony(以下简称“OpenHarmony”)系统 HDF 驱动框架采用 C 语言面向对象编程模型构建,通过平台解耦、内核解耦,来达到兼容不同内核,统一平台底座的目的,从而帮助开发者实现驱动一次开发,多系统部署的效果。

为了达成这个目标, OpenHarmony 系统 HDF 驱动框架提供了:

操作系统适配层(OSAL,Operating System Abstraction Layer):对内核操作相关接口进行统一封装,屏蔽不同系统操作接口。

平台驱动接口:提供 Board 部分驱动(例如,I2C/SPI/UART 总线等平台资源)支持,同时对 Board 硬件操作进行统一的适配接口抽象,方便开发者只需开发新硬件抽象接口,即可获得新增 Board 部分驱动支持。

驱动模型:面向器件驱动,提供常见的驱动抽象模型,主要达成两个目的。

1)提供标准化的器件驱动模型,开发者无需独立开发,通过配置即可完成驱动部署。

2)提供驱动模型抽象,屏蔽驱动与不同系统组件间的交互,使得驱动更具备通用型。

为了进一步简化 OpenHarmony 系统驱动开发,OpenHarmony 系统 HDF 驱动框架支持多种驱动加载方式:

支持驱动动态加载和静态加载,解除驱动代码和框架间的直接代码依赖,使得驱动程序可以独立编译和部署;

支持按需动态加载方式,避免设备驱动全量加载,可有效降低系统资源的占用。

本文主要分析 OpenHarmony 系统驱动加载过程,在正式介绍之前,首先了解 OpenHarmony 系统驱动架构的组成、工作原理和机制,从而了解驱动加载的细节。

OpenHarmony系统

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 可以有多个实例。

说明Device Host 顾名思义就是驱动宿主,提供驱动运行的环境。 当驱动部署在用户态时,Device Host 可以由独立的进程进行承载, 当驱动在部署在内核态时,Device Host 仅表示逻辑隔离。 Device Host 的划分原则: Device Host 属于一类设备聚合,如 Camera,Audio,Display 等。 驱动程序是部署在一个 Device Host 还是部署在不同的 Device Host,主要考虑驱动程序之间是否存的业务耦合性,如果两个驱动程序之间存在依赖,可以考虑将这部分驱动程序部署在统一 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 机制,使得不同部署形态下驱动接口趋于形式一致。驱动接口主要存在以下几种实现:

当驱动以内核组件部署时,客户端程序访问驱动程序需要通过 system call 方式调用,驱动接口通过 IO Service 请求将消息通过 system call 方式调用到内核,并将消息分发到 IO Dispatcher 处理。

当驱动以用户态服务形式部署时,客户端进程访问驱动进程需要通过 IPC 方式通信,IO Service 完成 IPC 通信的客户端消息请求封装,IO Dispatcher 完成驱动服务端消息请求封装,客户端消息通过 IPC 通信到达服务端并分发给 IO Dispatcher 处理。

当驱动部署在 RTOS(Real-Time Operating System)轻量化操作系统时,驱动接口和驱动程序之间采用的是 Function Call 方式调用,因此驱动接口仅提供定义,驱动接口实现由驱动程序提供。

Device Manager 提供了统一的驱动加载管理机制和驱动接口发布机制。

当 Device Host 环境加载完成时,Device Manager 根据 Device Information 信息,请求 Host 加载相应的驱动程序,Device Host 在收到请求时,进行以下操作:

1.根据请求加载设备信息,查找并加载指定路径下驱动镜像或从指定段地址(section)查找驱动程序入口。

2.查找驱动设备描述符,匹配对应的设备驱动。

3.当驱动匹配成功时,加载指定驱动程序镜像。

4.Host Framework 在驱动程序镜像加载成功后,调用驱动程序(Driver Entry)的绑定接口和初始化接口,实现与驱动程序的服务对象绑定,同时初始化设备驱动程序。

5.当 Device Information 配置中的服务策略要求对外暴露驱动接口时,驱动框架就将驱动程序的服务对象添加到对外发布的服务对象列表中,外部客户端程序就可以通过此列表来查询并访问相应的服务接口。

对于驱动接口实现而言:

当驱动部署在内核态时,驱动接口部署在用户态,驱动实现在内核态,驱动接口和驱动实现之间通过 syscall 调用方式实现调用交互。

当驱动部署在用户态时,驱动接口和驱动实现分别部署在两个进程中。驱动接口和驱动实现之间通过 IPC 调用方式实现调用交互。

为了使客户端和服务端驱动调用方式基本一致,驱动框架提供 IO Service 和 IO Dispatcher 机制屏蔽了调用消息传递方式的差异。

驱动接口实现统一采用远程调用的方式实现,客户端驱动接口函数将请求序列化成内存数据,通过驱动框架提供的 IO Service 将消息发送到服务端处理,服务端在收到请求消息时通过 IO Dispatcher 机制将消息分发给消息处理函数处理,处理函数将反序列化内存数据解析成相应的请求。这样的做到好处是,开发者只需重点关注接口的定义,无需过多的关注如何实现不同平台上接口适配。

驱动加载过程分析

OpenHarmony 系统驱动根据驱动程序部署的不同方式,存在两种驱动加载方式:

动态加载方式:采用传统的 so(共享库)加载方式,驱动程序通过指定 Symbol 方式找到驱动函数入口进行加载。

静态加载方式:采用将驱动程序通过 Scatter 编译到指定的 Section,再通过访问指定 Section 对应的地址,找到驱动函数入口进行加载。

下面结合一个 Sample 示例代码,讲解驱动加载过程,重点分析静态加载方式下内核态驱动加载过程。 实现驱动程序初始化接口在 HDF 驱动框架中,HdfDriverEntry 对象被用来描述一个驱动实现。

struct HdfDriverEntry { int32_t moduleVersion; const char *moduleName; int32_t (*Bind)(struct HdfDeviceObject *deviceObject); int32_t (*Init)(struct HdfDeviceObject *deviceObject); void (*Release)(struct HdfDeviceObject *deviceObject);};

编写一个简单的驱动,首先需要实现驱动程序 (Driver Entry)入口中的三个主要接口:

Bind 接口:实现驱动接口实例化绑定,如果需要发布驱动接口,会在驱动加载过程中被调用,实例化该接口的驱动服务并和 DeviceObject 绑定。

Init 接口:实现驱动的初始化,返回错误将中止驱动加载流程。

Release 接口:实现驱动的卸载,在该接口中释放驱动实例的软硬件资源。

int SampleDriverBind(struct HdfDeviceObject *deviceObject){ HDF_LOGE("SampleDriverBind enter!"); static struct IDeviceIoService testService = { .Dispatch = SampleServiceDispatch, .Open = NULL, .Release = NULL, }; deviceObject->service = &testService; return HDF_SUCCESS;} int SampleDriverInit(struct HdfDeviceObject *deviceObject){ HDF_LOGE("SampleDriverInit enter"); return HDF_SUCCESS;} void SampleDriverRelease(struct HdfDeviceObject *deviceObject){ HDF_LOGE("SampleDriverRelease enter"); return;} struct HdfDriverEntry g_sampleDriverEntry = { .moduleVersion = 1, .moduleName = "sample_driver", .Bind = SampleDriverBind, .Init = SampleDriverInit, .Release = SampleDriverRelease,}; HDF_INIT(g_sampleDriverEntry);

导出驱动程序入口符号实现驱动程序初始化后,需要将驱动程序入口通过驱动声明宏导出,这样驱动框架才能在启动时识别到驱动程序的存在,驱动才能被加载:

#define HDF_INIT(module) HDF_DRIVER_INIT(module)

(左右滑动,查看更多)

这里将 HDF_INIT 宏展开:

#define HDF_SECTION __attribute__((section(".hdf.driver")))#define HDF_DRIVER_INIT(module) constsize_tUSED_ATTRmodule##HdfEntryHDF_SECTION=(size_t)(&(module))

(左右滑动,查看更多)

下面是其实现原理:

图4 Driver Entry内存分布

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

添加设备配置

在设备对应的 device_info.hcs 添加 sample 驱动的配置:

sample_host :: host { hostName = "sample_host"; sample_device :: device { device0 :: deviceNode { policy = 2; priority = 100; preload = 1; permission = 0664; moduleName = "sample_driver"; serviceName = "sample_service"; } }}

在配置中定义的 device 将在加载过程中产生一个设备实例,通过 moduleName 字段指定设备对应的驱动名称,从而将设备与驱动关联起来,其中,设备与驱动可以是一对多的关系,即可以实现一个驱动支持多个同类型设备。 驱动启动过程我们添加的驱动是如何被执行的呢?简单来说,在系统启动时,驱动框架先启动,通过解析配置文件获取到设备列表,通过读取".hdf.drivers"段读取到驱动程序(Driver Entry)列表,然后遍历设备列表与驱动程序列表进行匹配,并加载匹配成功的驱动。驱动框架有两大核心管理者:

DeviceManager 负责设备的管理,包括设备加载、卸载和查询等设备相关功能。

DeviceServiceManager 负责管理设备发布的接口服务,提供接口服务的发布、查询等功能。

驱动加载主要由 DeviceManager 主导,首先 DeviceManager 要解析配置文件中的 Host 列表,根据 Host 列表中的信息来实例化对应的 Host 对象。Host 解析配置文件获取到关联的设备列表,遍历设备列表去获取与之匹配的驱动程序名称,然后基于驱动程序名称遍历前面提到的.hdf.driver section 获得驱动程序地址。

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

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

Device Manager 遍历设备列表,当查找到对应驱动实现时,为设备创建 Device 对象实例,如果设备配置中的 policy 字段为需要对外发布的驱动接口(SERVICE_POLICY_CAPACITY),那么驱动的 Bind 接口将首先被调用,用于关联设备和服务实例。然后驱动的 Init 接口将被调用,用于完成驱动的相关初始化工作。如果驱动被卸载或者因为硬件等原因 Init 接口返回失败,Release 将被调用,用于释放驱动申请的各类资源。

总结

本次和大家分享了 OpenHarmony 系统驱动的主要设计思想,重点分析了内核态驱动加载的过程,关于 OpenHarmony 系统驱动其他内容,后续会有更多技术文章向大家持续分享,敬请期待。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动
    +关注

    关注

    12

    文章

    1838

    浏览量

    85262
  • 框架
    +关注

    关注

    0

    文章

    403

    浏览量

    17475
  • HarmonyOS
    +关注

    关注

    79

    文章

    1973

    浏览量

    30143
  • OpenHarmony
    +关注

    关注

    25

    文章

    3713

    浏览量

    16254
收藏 人收藏

    评论

    相关推荐

    HarmonyOS NEXT应用元服务开发Intents Kit(意图框架服务)本地搜索方案概述

    一、概述 本地搜索是在HarmonyOS归一化搜索特性,开发者将应用/元服务内的功能和内容通过意图框架共享到HarmonyOS,即可实现“一步搜索,内容直达”。 二、典型场景 以“音乐垂域”的“歌曲
    发表于 11-06 10:59

    Openharmony软件评估指南-米尔瑞芯微RK3568开发板

    Openharmony软件评估指南用于介绍在米尔的开发板上运行Openharmony系统下的核心资源与外设资源的测试步骤与评估方法。本文可作为前期评估指南使用,也可以作为通用系统开发的
    发表于 09-06 20:06

    【迅为RK3568开发板】OpenHarmony学习开发系列教程(第1期 北向基础篇一)

    P1P0_先导课1:30 P2P1_OpenHarmony系统概述8:12 P3P2_OpenHarmony功能框架5:38 P4P3_
    发表于 08-16 15:27

    鸿蒙OpenHarmony南向/北向快速开发教程-迅为RK3568开发板

    4.1学习之旅了吗?快来加入我们,一起探索鸿蒙4.1系统的无限魅力吧! 【北京迅为】OpenHarmony学习开发系列教程(第1期 北向基础篇一) P0_先导课 P1_OpenHarmony
    发表于 07-23 10:44

    OpenHarmony之开机优化

    OpenHarmony已经支持了Bootchart工具,我们可以直接使用Bootchart工具,Bootchart工具介绍如下: 概述 Bootchart是一个用于系统启动过程性能分析的开源软件工具
    发表于 07-01 16:39

    OpenHarmony 成功亮相国际学术会议 ASPLOS 2024

    OpenHarmony的分布式特性、并发验证框架及可信执行环境,并与来自全球各地的专家学者深入探讨了其在移动操作系统、分布式系统系统架构设
    的头像 发表于 05-16 09:28 419次阅读
    <b class='flag-5'>OpenHarmony</b> 成功亮相国际学术会议 ASPLOS 2024

    鸿蒙开发:【OpenHarmony 4.0 Release指导】

    OpenHarmony 4.0版本如期而至,开发套件同步升级到API 10。相比3.2 Release版本,新增4000多个API,应用开发能力更加丰富;HDF新增200多个HDI接口,硬件适配更加便捷;我们持续优化图形框架和方
    的头像 发表于 05-14 09:59 1455次阅读
    鸿蒙开发:【<b class='flag-5'>OpenHarmony</b> 4.0 Release指导】

    鸿蒙OpenHarmony【快速入门概述

    OpenHarmony是一款面向全场景的开源分布式操作系统,采用组件化设计,支持在128KiB到xGiB RAM资源的设备上运行系统组件,设备开发者可基于目标硬件能力自由选择系统组件进
    的头像 发表于 04-19 15:14 442次阅读
    鸿蒙<b class='flag-5'>OpenHarmony</b>【快速入门<b class='flag-5'>概述</b>】

    鸿蒙开发实战:【Hdf Framework】

    该仓主要存放OpenHarmony驱动系统核心源码信息(包括驱动框架、配置管理、配置解析、驱动
    的头像 发表于 03-21 20:29 493次阅读
    鸿蒙开发实战:【<b class='flag-5'>Hdf</b> Framework】

    【六】Purple Pi OH开发板带你7天入门OpenHarmony

    原子开源基金会(OpenAtomFoundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代、基于开源的方式,搭建一个智能终端设备操作系统框架
    的头像 发表于 03-14 08:31 542次阅读
    【六】Purple Pi OH开发板带你7天入门<b class='flag-5'>OpenHarmony</b>!

    介绍一种OpenAtom OpenHarmony轻量系统适配方案

    本文在不改变原有系统基础框架的基础上, 介绍了一种OpenAtom OpenHarmony(以下简称“OpenHarmony”)轻量系统适配
    的头像 发表于 03-05 09:24 1138次阅读
    介绍一种OpenAtom <b class='flag-5'>OpenHarmony</b>轻量<b class='flag-5'>系统</b>适配方案

    OpenHarmony4.0源码解析之媒体框架

    及 audio-source 插件调用音频框架的播放及采集功能来实现音频的播放与录制;通过 surface-sink 调用图形框架,video-decoder 调用解码驱动
    的头像 发表于 02-26 22:05 905次阅读
    <b class='flag-5'>OpenHarmony</b>4.0源码解析之媒体<b class='flag-5'>框架</b>

    OpenHarmony 之 NAPI 框架介绍

    环境中的 JS 变量与方法。 OpenHarmony 中的 NAPI OpenAtom OpenHarmony(以下简称 “OpenHarmony”)应用层基于 javascript 语言开发,而
    的头像 发表于 02-01 17:34 692次阅读
    <b class='flag-5'>OpenHarmony</b> 之 NAPI <b class='flag-5'>框架</b>介绍

    OpenHarmony社区运营报告(2023年12月)

    17.5 万行(未包含 Flutter)。 • 九联开鸿:贡献芯片内核驱动HDF 驱动系统、应用样例等领域特性,新增 13 万行。 • 润开鸿:贡献芯片开发板、原生应用、ArkU
    发表于 01-10 15:44

    OpenHarmony开源GPU库Mesa3D适配说明

    ,对下使用Gallium框架,屏蔽驱动差异。在RK3568中,panfrost对ARM GPU提供了非常好的开源驱动支持。 二、适配方法 在RK3568 GPU 开源库mesa3D适配时,我们同时依赖
    发表于 12-25 11:38