zoukankan      html  css  js  c++  java
  • Android深度探索HAL读书笔记9

    看了本书第九章,我学习到了:

    1. HAL(抽象硬件层)是建立在linux驱动之上的一套程序库,这套程序库是属于内核层之上的应用层——系统运行库层。
    2. Linux驱动代码类型:访问硬件寄存器的代码和业务逻辑代码。
    3. Linux内核采用GPL协议,该协议要求源代码必须开源,即linux驱动必须开源。
    4. Android增加HAL的目的:①避免应用程序直接访问linux驱动②保护私人财产,满足不想开源的linux驱动作者的要求,带HAL的linux驱动相当于将数据从HAL传到寄存器,即从寄存器传到HAL的“数据二传”。

    总结:1)统一硬件的调用接口。2)解决GPL版权问题:由于linux、android分别基于不同的协议(GPL、Apache Licence2.0),增加HAL可使敏感代码摆脱GPL协议。3)利用位于用户空间的HAL代码辅助linux驱动完成一些特殊要求。

    1. HAL最初&新版本架构:

    ①   最初架构:在android系统中使用程序库(.so文件)调用内核空间的linux驱动,然后android应用程序(.APK)可以通过NDK程序访问HAL中的程序库,或直接在android应用程序中访问HAL的程序库。

    ②   新版本的架构:在旧的架构中加入了HAL架构要求的入口代码以便被安卓系统识别。通过调用id来定位相应的Stub(.so)。Service程序库(.so)位于Stub、JNI之间,该层库文件使用安卓系统提供的调用HAL的机制访问HAL中的Service程序库,该层通过id定位HAL Library,然后安卓apk再调用Service程序库。

    1. Android HAL的源码存储位置一般存储在<Android源码目录>/libhardware目录中,或<Android源码目录>/hardware目录中。

    最终编译生成的.so文件主要放在android系统的/system/lib/hw目录

    1. 为LED驱动加入HAL意义:应用程序无需再关心linux驱动和设备文件的交互方式,只需像访问API一样就可以linux驱动进行交互。
    2. 编写支持HAL的linux驱动:

    ①   编写linux驱动:驱动代码尽量简洁,尽可能将业务逻辑放入HAL库中

    ②   编写HAL Library:HAL Library就是linux库(*.so)文件。这类库文件有个接口通过HAL_MODULE_INFO_SYM变量实现。Service Library通过这个接口中定义的id定位Library。

    ③   编写Service Library:Service Library可以是linux Library也可以是JNI Library。本章LED驱动例子Service Library就是JNI Library。这一步除了用c/c++实现*.so库文件外还包含一个用java编写的服务管理类(SeviceManager),该类会调用Service Library,Apk程序会调用该类访问Service Library。

    1. 使用HAL层的LED驱动只保留创建设备文件及寄存器交互的代码,在设备文件的read、write函数中读写指定的寄存器。基本原理:从指定寄存器读取或写入5个字节的数据就可以读写指定寄存器,第一个字节指定读写的动作及寄存器类型,后4个寄存器是读写的实际数据。
    2. 带有HAL层的LED驱动代码除了read、write函数,其他代码与不带HAL层的基本相同。Read、write函数删除了所有与LED相关逻辑,只使用了iowrite32、ioread32函数读写指定寄存器。

    在read函数读取数据之前先获取了mem数组的第一个字节(mem[0]),以便确定寄存器类型。

    1. 进入hal层目录,执行#sh build.sh编译和安装LED驱动。该脚本文件中引用了一个common.sh脚本文件,common.sh脚本文件实现了find_devices函数用于显示android设备列表,并允许用户选择某一个android设备,最后返回设备的id。
    2. 测试读写寄存器:通过命令行参数“rwdev <r|w> <dev_file> <byte_count> [byte1] [byte2] … [byten]”传递设备文件名、字节数、要传递的字节等信息。执行read_write_dev目录中的build.sh脚本文件,直接调用交叉编译器(arm-none-linux-gnueabi-gcc)编译rw_dev.c,使用adb push命令将rwdev命令上传到开发板的/data/local目录。
    3. 编写调用LED驱动的HAL模块:HAL模块由leds_hal.c和leds_hal.h组成。leds_hal.h用于定义结构体、宏和引用一些系统的头文件。leds_hal.c引用了leds_hal.h和leds_hal_define.h头文件。

    ①   定义结构体和宏:hw_module_t,hw_device_t,hw_module_methods_t

    ②   编写HAL模块的open函数:是HAL的入口点,其工作:初始化hw_device_t的子结构体、打开设备文件、初始化寄存器

    ③   定义hw_module_methods_t结构体变量

    ④   定义HAL_MODULE_INFO_SYM变量:该变量类型一般为hw_module_t或其子结构体,该步中一般会初始化一些hw_module_t或其子结构体的成员变量,其中id表示HAL模块中android系统的标识,使用HAL模块的程序通过该id找到并装载HAL模块;methods变量指向hw_module_methods_t结构体的地址。

    ⑤   编写HAL模块的close函数

    ⑥   编写控制LED的函数:led_on、led_off

    1. 在android源码目录的hardware子目录建立一个leds_hal符号链接,在leds_hal目录下建立一个Android.mk文件,使用“mm”命令编译
    2. 执行build.sh脚本文件“#sh build.sh”编译和安装HAL模块
    3. adb shell命令进入开发板终端,HAL模块通常被放在/sysem/lib/hw下,文件名为“led_hal.default.so”
    4. 编写调用HAL模块的Service
    5. 编写调用Service的java库
    6. 测试LED驱动
  • 相关阅读:
    mysql-5-aggregation
    mysql-4-functions
    mysql-3-orderby
    技术之心 | 云信和TA们携手打响防疫战
    疫情下的传统商企自救|4个Tips搭建销量过亿直播间
    那些2019年会爆发的泛娱乐黑科技风口
    流量难、获客难、增长难?增长黑客思维“解救”B端业务
    【翻译】Facebook全面推出Watch Party,可多人线上同看直播视频
    深入浅出聊一聊Docker
    C++写日志方法调试
  • 原文地址:https://www.cnblogs.com/cqj0818/p/5642055.html
Copyright © 2011-2022 走看看