硬件抽象层(HAL).ppt_第1页
硬件抽象层(HAL).ppt_第2页
硬件抽象层(HAL).ppt_第3页
硬件抽象层(HAL).ppt_第4页
硬件抽象层(HAL).ppt_第5页
已阅读5页,还剩28页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第9讲硬件抽象层 HAL 讲师 李宁 讲师李宁 主要内容 什么是HAL为什么要在Android在添加HAL编写和测试基于HAL的LED驱动 讲师李宁 什么是HAL HAL HardwareAbstractionLayer 硬件抽象层 是建立在Linux驱动之上的一套动态库 这套动态库并不属于Linux内核 而是属于Linux内核层之上的系统运行库层 Google为Android增加HAL的主要目的除尽量避免应用程序直接访问Linux驱动外 还有一个重要原因 那就是保护 私人财产 对于那些既想发布基于Android的Linux驱动程序 又不想将核心业务逻辑公开的企业或个人 HAL简直就是福音 讲师李宁 为什么要在Android中加入HAL 讲师李宁 加入HAL的主要目的 统一硬件的调用接口 由于HAL有标准的调用接口 所以可以利用HAL屏蔽Linux驱动复杂 不统一的接口 解决了GPL版权问题 由于Linux内核基于GPL协议 而Android基于ApacheLicence2 0协议 因此Google玩了个 穿越 将原本位于Linux内核中的Linux驱动的敏感代码向上移了一个层次 这样这些敏感代码就摆脱了GPL协议的束缚 那写不想开源的Linux驱动作者也就没必要开源了 针对一些特殊的要求 对于有些硬件 可能需要访问一些用户空间的资源 或在内核空间不方便完成的工作以及特殊需求 在这种情况下 可以利用位于用户空间的HAL代码来辅助Linux驱动完成一些工作 讲师李宁 AndroidHAL的旧架构 讲师李宁 AndroidHAL的新架构 讲师李宁 AndroidHAL程序库的路径 AndroidHAL的源代码存储的位置并不固定 一般会存储在 hardware目录中 其中 hardware libhardware legacy用于保存旧的HAL架构的源代码 新HAL架构的源代码在 hardware libhardware目录中 当然 这些源代码可以放在 hardware或其他的目录 最终编译生成的 so文件主要放在Android系统的 system lib hw目录 也可以放在其他的目录 讲师李宁 精简LED驱动 基于HAL的LED驱动去掉了所有与读写寄存器规则相关的代码 只保留了创建设备文件已经与寄存器交互的代码 不涉及到任何规则 只是将数据简单地写入指定的寄存器 或从指定的寄存器读取数据 LED驱动利用了设备文件的read和write函数来读写指定的寄存器 基本原理是只从指定寄存器读取或写入5个字节 第1个字节用于指定读写的动作以及寄存器 后4个字节是读写的实际的数据 因为LED驱动只涉及到操作一个int类型数据的寄存器 因此使用4个字节个来表示一个int类型的数据 在与LED驱动交互是 只要向设备文件 dev s3c6410 leds hal 读取或发送5个字节的数据 就可以读写指定的寄存器 讲师李宁 测试读写寄存器操作 由于LED驱动程序的设备文件接收的不是字符串 而是字节类型的数据 字节数组 因此需要单独做一个程序向设备文件写入字节形式的数据 或从设备文件中读取字节类型的数据 命令行参数来传递设备文件名 字节数和要传递的字节等信息 命令行语法格式如下 rwdev byte1 byte2 byten 编译rw dev c程序arm gcc static o root drivers read write dev rwdev root drivers read write dev rw dev c 讲师李宁 调用LED驱动的HAL程序库 1 任何被系统自动调用的程序都会有一个标准的接口 这个接口相当与一个约定的规则 不管任何程序 只要遵循这个规则 就可以成功被调用 例如 C语言可执行程序都会有一个main函数 系统中执行程序是都会寻找main函数来执行 Linux驱动也有多个接口 最常用的就是init和exit函数 除此之外 还有与设备文件相关的read write ioctl等函数 只要Linux驱动程序安装接口的要求定义和实现 就可以成功安装在Linux驱动中 讲师李宁 调用LED驱动的HAL程序库 2 既然HAL程序库也可以被Android系统自动调用 那么自然也拥有标准的接口 只不过这个接口不是函数 而是一个固定名称的结构体变量HAL MODULE INFO SYM 也就是说 所有的HAL程序都必须要有一个HAL MODULE INFO SYM变量 并且初始化该结构体变量的common成员变量 讲师李宁 调用LED驱动的HAL程序库 3 第1步 定义结构体和宏编写HAL程序库需要使用到3个非常重要的结构体 hw module t hw device t和hw module methods t 在第1步需要定义两个新的结构体 这两个结构体的第1个变量的类型必须是hw module t和hw device t 一般还需要为HAL模块定义一个ID 实际上在这1步就是编写leds hal h头文件的代码 讲师李宁 调用LED驱动的HAL程序库 4 typedefstructhw module t 模块的Tag 值必须是HARDWARE MODULE TAG uint32 ttag 模块主版本号 uint16 tversion major 模块从版本号 uint16 tversion minor 模块的ID 通过该ID可以找到当前模块 constchar id 模块名称 constchar name 模块作者 constchar author 与模块相关的函数指针 都包含着hw module methods t结构体中 structhw module methods t methods 模块的dso dlopen函数返回的HAL动态库的handler void dso 保留的空间 uint32 treserved 32 7 hw module t 讲师李宁 调用LED驱动的HAL程序库 5 描述硬件设备 或称为HAL设备 的结构体hw device t typedefstructhw device t 设备的Tag 值必须是HARDWARE DEVICE TAG uint32 ttag 硬件设备的版本号 uint32 tversion 指向描述硬件模块的hw module t结构体指针 structhw module t module 保留的内存空间 uint32 treserved 12 关闭设备的函数指针 int close structhw device t device hw device t 讲师李宁 调用LED驱动的HAL程序库 6 描述模块入口函数的结构体hw module methods t typedefstructhw module methods t 打开设备是调用的open函数的指针 int open conststructhw module t module constchar id structhw device t device hw module methods t 在这3个结构体中 hw module t是最先使用到的 然后通过hw module t methods找到hw module methods t open函数 并调用该函数 这个open函数相当与HAL程序库的入口函数 一般会在这个函数里打开设备文件 初始化hw device t结构体设置一些控制硬件设备的函数 讲师李宁 调用LED驱动的HAL程序库 7 在第1步先考虑hw module t和hw device t两个结构体 HAL规则建议不直接使用hw module t和hw device t 直接使用这 而要新定义两个结构体 将hw module t和hw device t分别作为新结构体的第1个变量的类型 就像leds hal h文件中的led module t和led control device t 那么HAL为什么要这么建议呢 讲师李宁 调用LED驱动的HAL程序库 8 在说明原因之前 先看一下led device open函数和led control device t结构体 staticintled device open conststructhw module t module constchar name structhw device t device structled control device t structhw device thw device int set on structled control device t dev int32 tled int set off structled control device t dev int32 tled 讲师李宁 调用LED驱动的HAL程序库 9 led device open函数将在NDK程序中被调用 该函数的最后1个参数类型是hw device t 不过在调用该函数时 传进来的却是led control device t 从这一点看 hw device t相当与led control device t的父类 C语言中并没有类的概念 这样解释只是便于理解 也可以称为其父结构体 在调用led device open函数时将led control device t 强行转换成了hw device t 对于C语言来说 这样的转换要满足一个条件 就是做为父结构体 hw device t 的结构体必须是子结构体 led control device t 的第1个变量的数据类型 讲师李宁 调用LED驱动的HAL程序库 10 那么为什么要这样做强行转换呢 主要是因为扩展的需要 因为在led control device t结构体中定义了两个函数指针变量 set on和set off 这两个变量的名称和参数个数 参数类型是任意指定的 但为了使HAL程序库保持独立性 可能会被多个NDK模块使用 每个NDK模块使用了不同的hw device t和hw module t的子结构体 HAL程序库在的方法只能使用hw device t和hw module t作为参数类型 而如果不使用hw device t和hw module t的父类 就意味这无法添加这种设备函数指针 set on和set off 等成员 那么这个HAL程序库就成了中看不中用的 东西 了 光有逻辑代码 却无法向外部提供与其交互的接口 讲师李宁 调用LED驱动的HAL程序库 11 由于在led module t结构体除了hw module变量外 没有任何其他的成员 因此 HAL MODULE INFO SYM的类型可以直接定义成hw module t 代码如下 structhw module tHAL MODULE INFO SYM tag HARDWARE MODULE TAG version major 1 version minor 0 id LED HARDWARE MODULE ID name SampleLEDHALStub author Lining methods 讲师李宁 调用LED驱动的HAL程序库 12 第2步 编写打开设备的open函数设备的打开函数是HAL模块的入口点 在本例中是led device open函数 设备打开函数主要做如下3项工作 初始化hw device t的子结构体 除了设置也写必要的变量外 还需要设置操作硬件的函数指针 本例是close set on和set off 其中set on和set off在调用HAL模块的代码中要使用到 close有系统自动调用 在这一步与close set on和set off惯量的函数还没有定义 可以先把函数名写上 或在定义了相关函数后再设置这些函数指针 打开设备文件 初始化寄存器 讲师李宁 调用LED驱动的HAL程序库 13 第3步 定义hw module methods t结构体变量HAL模块需要hw module methods t结构体的open函数指针变量指定open入口函数 第4步 定义HAL MODULE INFO SYM变量所有的HAL模块都必须有一个HAL MODULE INFO SYM变量 该变量的类型一般为hw module t或其子结构体 该变量初始化了一些变量 其中id和methods成员最重要 id表示HAL模块中Android系统中的索引 使用HAL模块的程序并不是直接装载 so文件 而是通过这个id找到并装载HAL模块 methods变量的值需要设置在第3步定义的hw module methods t结构体变量 当调用者通过id找到并装载HAL模块后 就会通过methods变量调用open入口函数来初始化设备 讲师李宁 调用LED驱动的HAL程序库 14 第5步 编写卸载设备的close函数当HAL模块被卸载后会调用close函数 在本例中是led device close函数 该函数需要在第2步的led device open函数中赋给hw device t的close成员变量 第6步 编写控制设备的函数根据设备类型和功能的不同 这一步编写的函数也有所不同 在本例中编写了两个控制函数 led on和led off 分别用来控制LED的开 关 led on和led off函数需要在第2步编写的led device open函数中赋给led control device t set on和led control device t set off变量 讲师李宁 编写调用HAL程序库的Service 调用HAL程序库涉及到一个非常重要的hw get module函数 该函数可以通过在leds hal h中定义的LED HARDWARE MODULE ID宏 led hal 查找LEDHAL模块 并获得led module t结构体 然后调用led module t hw module methods open函数来初始化LED驱动 并通过open函数返回led control device t结构体 在led control device t结构体中包含了在HAL模块中定义的控制LED驱动的函数指针 set on和set off 为Service建立符号链接ln s root drivers s3c6410 leds hal leds hal jni working android2 3 4 src frameworks base services leds hal jni 讲师李宁 HAL的存放路径和命名规则 1 HAL程序库 so文件 通常存放在 system lib hw目录 文件名中一般都有一个default 例如 led hal default so文件是LED驱动的HAL程序库 那么这个存放目录和文件名是我们的唯一选择吗 在回答这个问题之前 需要先查看一下调用HAL程序库的核心函数hw get module的代码 因为正是这个函数利用HAL模块的ID找到了HAL程序库的 so文件 所以一切的秘密都会在这个函数的揭开 hw get module函数位于hardware c文件中 hardware c文件的完整路径如下 working android2 3 4 src hardware libhardware hardware c 讲师李宁 HAL的存放路径和命名规则 2 在阅读完hardware c文件的代码和注释后 可以得出如下结论 这些结论也恰好回到了本节开始提出的问题 HAL模块库文件的存放路径有两个 system lib hw和 vendor lib hw hw get module函数会先从 system lib hw目录根据库文件命名规则寻找库文件 如果 system lib hw目录没有库文件 hw get module会按同样的规则在 vendor lib hw目录中寻找 HAL模块库文件的命名规则是ID suffix so 其中ID功过hw get module函数的id参数指定 suffix 后缀 通过在属性文件中指定 hw get module会在Android系统的属性文件中根据variant keys数组中定义的4个key依次查找suffix 如果未找到suffix 使用默认的suffix default 讲师李宁 HAL的存放路径和命名规则 3 在上面的几点多次提到了属性文件 那么这个属性文件到底是什么呢 实际上 Android系统的属性文件共有如下4个 default prop system build prop system default prop data local prop 讲师李宁 HAL的存放路径和命名规则 4 Android在启动时会自动装载这些属性文件 如果在多个属性文件中都定义了同一个Key和Value 那么只用第一个Key被获取 例如 在 default prop文件中定义了ro product board的值为abc 而在 system build prop文件中定义了ro product boardd的值为xyz 那么hw get module函数会把 default prop文件中的abc作为HAL模块库文件的后缀 而不会再读取 system build prop文件中的xyz 因此 HAL模块的库文件名是 假设ID是led hal led hal abc so 讲师李宁 HAL的存放路径和命名规则 5 4个属性文件名在如下文件定义了4个宏 在以后的Android版本中有可能增加新的属性文件 working android2 3 4 src bionic libc include sys system proper

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论