zoukankan      html  css  js  c++  java
  • 第九章 硬件抽象层:HAL

    1.在传统的Linux系统中Linux驱动一般有两种类型的代码:访问硬件寄存器的代码和业务逻辑代码.

    2.android的层次结构:应用层,应用框架层,系统运行库层,linux内核层

    3.为android加入HAL的目的:

    (1)统一硬件的调用接口.由于HAL有标准的调用接口,所以可以利用 HAL屏蔽Linux驱动复杂,不统一的接口.

    (2)解决GPL版权问题。由于 Linux 内核基于GP协议,而Android基于Apache Licence2.0协议

    (3)针对一些特殊的要求.对于有些硬件,可能需要访问一些用户空间的资源,或在内核空间不方便完成的工作以及特殊需求。在这种情况下 ,可以利用位于用户空间的HAL代码来辅助 Linux驱动完成一些工作.

    4.HAL架构比较简单,其基本原理就是在 Android 系统中使用程序库,调用位于内核空间的linux驱动.调用HAL模块的代码并不需要直接装载.so 文件,而只需要通过一个ID来定位相应的.so文件.

    5.编写一款支持HAL的linux驱动程序的步骤

    (1)编写linux驱动.代码要简洁,将逻辑业务放到HAL Library中

    (2)编写HAL Library.Service Library就是通过接口中定义的ID定位HAL

     (3)编写Service library.Service Manager会调用 Service Library,而APK 程序会调用Service Manager类访问 Service Library

    6.编写LED驱动时注意:

    (1)s3c6410_leds_hal.c文件中的代码除了 s3c64lO_leds_ hal_read 和 s3c641O leds_ hal_write函数(相对于第7章的LED驱动s3c6410_1eds_read 和s3c64lO_leds_ write函数)中的代码外,其他的代码与第7章实现的LED 驱动的代码基本相同.

    (2)在s3c6410_leds_hal_read 和s3c6410_leds_hal_write函数中己经删除了所有与 LED 相关的逻辑。只使用了 iowrite32 和 ioread32 函数读写指定的寄存器.通过 s3c641O_leds_hal_read 和s3c6410_leds_hal _write 函数中的代码是无法看出操作 GPM 寄存器的业务逻辑的.

     (3)在 s3c6410_leds_hal_read 函数中在读取寄存器数据之前,先获取了 mem 数组的第l个字节(mem[O]),该字节表示寄存器类型。在设备文件读取数据之前,需要先向设备写入这个字节(其余 4 个字节可以是任意值,也可以不传值),以便事先确定要操作的寄存器类型.

    7.编译和安装LED驱动:# sh build.sh

    8.LED 驱动程序的设备文件接收的不是字符串,而是字节类型的数据(字节数组),因此需要单独做一个程序向设备文件写入字节形式的数据 ,或从设备文件中读取字节类型的数据.

    rwdev <rlw> <dev_file> <byte_count> [bytel] [byte2」 ... [byten]

    # 执行read_write_dev目录中的build.sh 脚本文件,该脚本文件用于编译 rw.dev.c文件

    # 并上传可执行文件(rwdev)开发板

    sh /root/drivers/read_write_dev/build.sh

    # 下面的两行语句用于测试 LED 驱动

    #向开发板的GPMDAT(3表示向 GPMDAT 寄存器写入数据,见 LED 驱动中定义的宏)寄存器写入数据

    #写入的数据是30000,分别表示5个字节的10 进制表示,执行结果是4个LED全部点亮

    adb shell /data/1o cal/rwdev w /dev/s3c6410_leda_hal 530000

    # 从GPMDAT寄存器 读取数据(6表示从 GPMDAT 寄存器读取数据)。

    # 在读取数据时只需要指定第1个字节即可,该字节用于指定读取那个寄存器中的数据

    adb shell '/data/local/rwdav r /dev/a3c6410_leda_bal 5 6'

    下面看看read_write_dev目录中的build.sh脚本文件的代码

    # 交叉编译器要使用- static 选项,将所需要的程序库全部连接进可执行程序,否则 rwdev 无法正常执行

    arm-none- linux-gnueabi-gcc -static -o /root/drivers/read_write_dev/rwdev /root/dri ve

    rs /read write dev/rw_dev.c

    adb push /root/drivers/read_write_dev/rwdev/data/1ocal/rwdev

    9.HAL模块的步骤和原理

    (1)定义结构体和宏,用到三个非常重要的结构体(hw_module_t,hw_device_t,hw_module_ methods_t),还需要为HAL模块定义一个ID.hw_module_t是最先使用到的,然后通过 hw_module_t.methods 找到

    hw_module_methods_t.open函数,并调用该函数.这个 open函数相当于HAL模块的入口.一般在这个函数里打开设备文件、初始化 hw_device_t结构体以及一些控制硬件设备的函数.

     (2)编写HAL模块的open函数

    初始化hw_device_t的子结构体.

    打开设备文件.

    初始化寄存器

    (3)定义hw_module_methods_t结构体变量

    需要open函数指针变量指定open入口函数

    (4)定义HAL_MODULE_INFO_SYM变量

    所有的HAL模块都必须有一个 HAL_MODULE_INFO_SYM变量.该变量的类型一 般为hw_module_ t或其子结构体

    (5)编写HAL模块的close函数

    当HAL模块被卸载后会调用 close 函数

    (6)编写控制LED的函数

    由于HAL模块属于Android系统的一部分,因此不能像独立运行在ARM 处理器上的程序一样直接使用交叉编译器来编译。因为HAL需要很多Android-中的头文件和共享库。最简单的方法就是使用下面的命令在Android源代码目录的 hardware子目录建立一个leds_hal符号链接.然后进入hardware/leds_hal目录使用mm命令编译leds_hal.

    # ln -s /toot/drivers/ch09/s3c6410_1eds_hal/leds_hal /working/android2. 3. 4_src/hardware/leds_hal

    10.HAL模块(so文件)通常存放在system/lib/hw目录. 文件名中一 般都有一个 default.

    11.hardware.c 文件的代码并不复杂,只包含了两个函数(load和hw_get_ module)和一些变量和宏

    12.HAL 模块库文件的命名规则是ID.suffix.so.其中 TD 通过 hw_get_ module 函数的id 参数指定.suffix (后缀)通过属性文件指定.

    13.打开_system_properties.h文件后,就会在后面看到如下4个宏

    #define PROP_PATH_RAMDISK_DEFAULT      "/default.prop ”

    #define PROP_PATH_SYSTEM_BUILD         "/system/build.prop”

    #define PROP_PATH_SYSTEM_DEFAULT       ”/system/default.prop ”

    #define PROP_PATH_LOCAL_OVERRIDE       ”/data/local.prop”    

    14.编写调用Service的java库:为了使程序更易于使用,可以将调用 Service 程序库的 Java类单独封装在jar文件中,这样做任何的 Android 应用程序中只要引用了这个jar文件就可以向调用普通Java类一样访问LED驱动了.

    15.测试LED驱动:首先 test_s3c6410_leds-hal_eclipsejava 工程必须引用上一节生成的ledHalService.jar文件,然后S3C64lOLedHalMain.java 中编写代码控制LED

  • 相关阅读:
    ubuntu安装jdk的两种方法
    LeetCode 606. Construct String from Binary Tree (建立一个二叉树的string)
    LeetCode 617. Merge Two Binary Tree (合并两个二叉树)
    LeetCode 476. Number Complement (数的补数)
    LeetCode 575. Distribute Candies (发糖果)
    LeetCode 461. Hamming Distance (汉明距离)
    LeetCode 405. Convert a Number to Hexadecimal (把一个数转化为16进制)
    LeetCode 594. Longest Harmonious Subsequence (最长的协调子序列)
    LeetCode 371. Sum of Two Integers (两数之和)
    LeetCode 342. Power of Four (4的次方)
  • 原文地址:https://www.cnblogs.com/yqing/p/5653037.html
Copyright © 2011-2022 走看看