第九章 硬件抽象层: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

时间: 2024-12-30 03:28:22

第九章 硬件抽象层:HAL的相关文章

第九章 硬件抽象层:HAL

本章的主要内容是硬件抽象层:HAL.本章中了解的是编写HAL的Linux驱动程序的步骤,具体如下: 第一步:编写Linux驱动 “编写Linux驱动”,从表面上看没什么意义,但如果要为Linux驱动添加HAL,而且像尽量保护敏感数据.Linux驱动的代码就要尽量简洁,尽可能将业务逻辑放到HAL Library中. 第二步:编写HAL Library HAL Library就是普通的Linux Library(*.so)文件.但这类文件库有一个接口.通过HAL_MODULE_INFO_SYM变量实

第九章 硬件抽象层:HAL 心得笔记

1.HAL(Handerware Abstraction Layer,硬件抽象层)是建立在linux程序上的一套程序库,这套程序库并不属于内核,而是属于内核之上的应用层. 2.要在Android中加入HAL的原因:在linux驱动中一般有两种类型的代码:访问硬件寄存器的代码和业务逻辑代码.对于访问硬件寄存器的代码而言,并没有秘密,这都是调用linux内核的标准函数进行的标准操作. 3.Google为android加入HAL其主要目的在于: 统一硬件的调用接口: 解决了GPL版权问题: 针对一些特

第九章 硬件抽象层: HAL

HAL ( Hardware Abstraction Layer,硬件抽象层 )是建立在Linux 驱动之上的一套程序库.这套程序库并不属于Linux 内核, 而是属于Linux 内核层之上的应用层. 统一硬件的调用接口.由于HAL 有标准的调用接口,所以可以利用HAL屏蔽Linux 驱动复杂.不统一的接口.解决了GPL版权问题.由于Linux 内核基于GPL协议,而Android 基于Apache Licence 2 .0 协议.因此Google 玩了个“穿越”,将原本位于Linux驱动中的敏

第九章 硬件抽象层:HAL 读后感

Android HAL层,即硬件抽象层,是Google响应厂家“希望不公开源码”的要求推出的新概念1,源代码和目标位置源代码: /hardware/libhardware目录,该目录的目录结构如下:/hardware/libhardware/hardware.c编译成libhardware.so,目标位置为/system/lib目录2,HAL层的实现方式JNI->通用硬件模块->硬件模块->内核驱动接口具体一点:JNI->libhardware.so->xxx.xxx.so-

第九章硬件抽象层:HAL

1.HAL是建立在Linux驱动之上的一套程序库,这套程序库并不属于Linux内核,而是属于Linux内核层之上的应用层. 2.Google为Android加入HAL主要有如下的目的: 统一硬件的调用接口.解决了GPL版权问题. 3.加入HAL的驱动使应用程序不需要再关心Linux驱动和设备文件的交互方式,而只需要像访问普通API一样就可以和Linux驱动进行交互. 4.编写一款支持HAL的Linux驱动程序的步骤: 第一步:编写Linux驱动. 第二步:编写HAL Library 第三步:编写

Android深度探索(卷1)HAL与驱动开发 第九章&#160;硬件抽象层:HAL 读书笔记

HAL是建立在Linux驱动之上的一套程序库.这套程序库并不属于Linux内核,而是属于Linux内核层之上的应用层.HAL的主要目的一个是用来保护"私人财产",另一个是尽量避免应用程序直接访问Linux驱动程序. 传统的Linux系统中Linux驱动一般有两种类型的代码,访问硬件寄存器和业务逻辑代码.对于访问硬件寄存器代码,并无秘密可言,因为都是调用Linux内核的标准函数进行的标准操作.而Linux的业务逻辑部分对于有些企业或者个人并不想讲源代码公开.Linux内核采用GPL协议,

第九章 读书笔记

第九章 硬件抽象层 HAL 在传统的Linux.系统中Linux驱动一般有两种类型的代码:访问硬件寄存器的代码和业务逻辑有码.对于访问硬件寄存器的代码,并没有什么秘密可言,因为这都是调用的 Linux 内核的标准函数进行的标准操作4 而Linux驱动的业务逻辑部分对击有些企业或个人并不想将源代码公开.尽管这些Lipux.驱动都是免费给用户使用的,由于这些Linux 驱动的实现涉及一些,技术专利或商业秘窑,如果公开源代码会有很大麻烦.但作为Linux.驱动,又不得不公开源代码.这 是由于Linux

第九章 HAL

<Android深度探索>第九章讲的是硬件抽象层:HAL.HAL是建立在Linux驱动之上的一套程序库.这套程序库并不属于Linux内核,而是属 于Linux内核层之上的应用层.Google为Android加入HAL主要的目的:统一硬件的调用接口:解决了GPL版权问题:针对一些特殊的要求. 编写一款支持HAL的Linux驱动程序的步骤,第1步:编写Linux驱动:第2步:编写HAL Library:第3步:编写Server Library.在编写Linux驱动以及驱动相关的程序的过程中应分段测

Android深度探索(卷一)HAL与驱动开发 第九章

通过学习Android深度探索(卷一)HAL与驱动开发的第九章让我知道了HAL硬件抽象层,为什么要在Android中加入HAL和Android HAL架构. HAL是建立在Linux驱动之上的一套程序库.这套程序库并不属于Linux内核,而是属于Linux内核层之上的应用层,其主要目的除了尽量避免应用程序直接访问Linux驱动外,还有一个重要原因,那就是保护“私人财产”. 在传统的Linux系统中Linux驱动一般有两种类型的代码:访问硬件寄存器代码和业务逻辑代码.所以加入HAL的主要原因就是: