为什么要在Android中加入HAL
1.统一硬件的调用接口。由于HAL有标准的调用接口,所以可以利用HAL屏蔽Linux驱动复杂、不统一的接口。
2.解决了GPL版权问题。由于Linux内核基于GPL协议,而Android基于Apache Licence 2.0协议。因此Google玩了个“穿越”,将原本位于Linux内核中的Linux驱动的敏感代码向上移了一个层次。这样这些敏感代码就摆脱了GPL协议的束缚。那写不想开源的Linux驱动作者也就没必要开源了。
3.针对一些特殊的要求。对于有些硬件,可能需要访问一些用户空间的资源,或在内核空间不方便完成的工作以及特殊需求。在这种情况下,可以利用位于用户空间的HAL代码来辅助Linux驱动完成一些工作。
Android HAL架构:
旧架构: 新架构:
然后就要编写一个支持HAL的Linux驱动程序,其步骤为:
第一步:编写Linux驱动
第二步:编写HAL Library
第三步:编写Service Library
最后基于HAL的LED驱动去掉了所有与读写寄存器规则相关的代码,只保留了创建设备文件已经与寄存器交互的代码LED驱动利用了设备文件的read和write函数来读写指定的寄存器。基本原理是只从指定寄存器读取或写入5个字节。第1个字节用于指定读写的动作以及寄存器。后4个字节是读写
编写诵点LED驱动的HAL模块;
实际上:HAL模块也是普通的linux共享库(.so文件),只不过HAL模块可以被Android系统自动装载而不是开发人员自己去装载.so文件。.
Linux驱动的 init 函数与main函数的性质类似。在装载Linux驱动的过程中系统会调用init 函数.
既然HAL模块也可以被Android系统自动调用,那个自然也拥有类似main 或init函数的接口。只不过这个接口不是函数, 而是一个固定名称的结构体变量HAL_MODULE_INFO_SYM.
编写 HAL模块的步骤和原理如下:
第l步:定义结构体和宏:编写 HAL 模块需要使用到 3 个非常重要的结构体( hw_module_t 、 hw_device_t 和hw _ module_ method_ t), 在第 l 步需要定义两个新的结构体, 这两个结构体的第 l 个变量的数据类型必须是 hw_module_t和 bw_device_t。 除此之外, 还需要为HAL模块定义一个ID. 实际上在这 l 步就是编写leds_hal.h 头文件的代码。
第 2 步:编写 HAL模块的 open 函数:
open 函数是 HAL 模块的入口点。该函数主要做如下 3 项工作:初始化 hw device_t 的子结构体。打开设备文件。初始化寄存器。
第3 步:定义 hw_module_methods_ t 结构体变量
第4 步: 定义 HAL_MODULE_INFO_SYM 变量
第5步:编写 HAL模块的 close 函数
第 6步:编写控制 LED 的函数
总结:在LED的驱动中,我们加入HAL使用程序不需要关心Linux驱动和设备文件的交互方式。编写一款支持HAL的linux驱动程序的步骤:
第一步:编写linux驱动
第二步:编写 HAL Library
第三步:编写Service library
编写HAL模块的步骤和原理如下:
第一步:定义结构体和宏
描述HAL模块的hw-module-t结构体
描述HAL设备的HW-device-t结构体
描述模块入口函数的hw-module-methods-t结构体
第二步:编写HAL模块的open函数
第三步:定义hw-module-methods-t结构体变量
第四步:定义HAL-module-info-sym变量
第五步:编写HAL模块的close函数
第六步:编写控制LED的函数
本章中我学习到了:
1.在Android.系统中使用 Linux驱动有两种方式。 一种是通过传统的方式直接与Linux驱动交互。
2.编写宏时要了解如下俩个知识点:可变参数的宏、Do{.....}while(0)