没有合适的资源?快使用搜索试试~ 我知道了~
首页《Android驱动开发全过程》
资源详情
资源推荐
- 1 - ANDROID
自学精品系列——驱动篇
Android 硬件抽象层(HAL)概要介绍和学习计划
Android 的硬件抽象层,简单来说,就是对Linux 内核驱动程序的封装,向上提供接口,屏蔽低层的实现细
节。也就是说,把
对硬件的支持分成了两层,一层放在用户空间(User Space),一层放在内核空间(Kernel Space),其中,
硬件抽象层运行在
用户空间,而Linux 内核驱动程序运行在内核空间。为什么要这样安排呢?把硬件抽象层和内核驱动整合在
一起放在内核空间
不可行吗?从技术实现的角度来看,是可以的,然而从商业的角度来看,把对硬件的支持逻辑都放在内核
空间,可能会损害
厂家的利益。我们知道,Linux 内核源代码版权遵循GNU License,而 Android 源代码版权遵循Apache License,
前者在发布产
品时,必须公布源代码,而后者无须发布源代码。如果把对硬件支持的所有代码都放在Linux 驱动层,那就
意味着发布时要公
开驱动程序的源代码,而公开源代码就意味着把硬件的相关参数和实现都公开了,在手机市场竞争激烈的
今天,这对厂家来
说,损害是非常大的。因此,Android 才会想到把对硬件的支持分成硬件抽象层和内核驱动层,内核驱动
层只提供简单的访问
硬件逻辑,例如读写硬件寄存器的通道,至于从硬件中读到了什么值或者写了什么值到硬件中的逻辑,都
放在硬件抽象层中
去了,这样就可以把商业秘密隐藏起来了。也正是由于这个分层的原因,Android 被踢出了Linux 内核主线
代码树中。大家想
想,Android 放在内核空间的驱动程序对硬件的支持是不完整的,把Linux 内核移植到别的机器上去时,由
于缺乏硬件抽象层
的支持,硬件就完全不能用了,这也是为什么说Android 是开放系统而不是开源系统的原因。撇开这些争
论,学习Android 硬
件抽象层,对理解整个Android 整个系统,都是极其有用的,因为它从下到上涉及到了Android 系统的硬件
驱动层、硬件抽象
层、运行时库和应用程序框架层等等,下面这个图阐述了硬件抽象层在Android 系统中的位置,以及它和
其它层的关系:
在学习Android 硬件抽象层的过程中,我
们将会学习如何在内核空间编写硬件
驱动程序、如何在硬件抽象层中添加接口
支持访问硬件、如何在系统启动时
提供硬件访问服务以及 如何编写JNI 使
得可以通过Java 接口来访问硬件,而
作为中间的一个小插曲,我们还将学习一
下如何在Android 系统中添加一个C
可执行程序来访问硬件驱动程序。由于这
是一个系统的学习过程,笔者将分
成六篇文章来描述每一个学习过程,包括:
一. 在Android 内核源代码工程中编写硬
件驱动程序。
二. 在Android 系统中增加C 可执行程序
- 2 - ANDROID
自学精品系列——驱动篇
来访问硬件驱动程序。
三. 在Android 硬件抽象层增加接口模块访问硬件驱动程序。
四. 在Android 系统中编写JNI 方法在应用程序框架层提供Java 接口访问硬件。
五. 在Android 系统的应用程序框架层增加硬件服务接口。
六. 在Android 系统中编写APP 通过应用程序框架层访问硬件服务。
学习完这六篇文章,相信大家对Android 系统就会有一个更深刻的认识了,敬请关注。
在
Ubuntu
上为
Android
系统编写
Linux
内核驱动程序
这里,我们不会为真实的硬件设备编写内核驱动程序。为了方便描述为Android 系统编写内核驱动程序的
过程,我们使用一
个虚拟的硬件设备,这个设备只有一个4 字节的寄存器,它可读可写。想起我们第一次学习程序语言时,
都喜欢用“Hello, World”
作为例子,这里,我们就把这个虚拟的设备命名为“hello”,而这个内核驱动程序也命名为hello 驱动程序。
其实,Android 内
核驱动程序和一般Linux 内核驱动程序的编写方法是一样的,都是以Linux 模块的形式实现的,具体可参考
前面Android 学习
启动篇一文中提到的Linux Device Drivers 一书。不过,这里我们还是从Android 系统的角度来描述Android
内核驱动程序的编
写和编译过程。
一. 参照这两篇文章在Ubuntu 上下载、编译和安装Android 最新源代码和在Ubuntu 上下载、编译和安装
Android 最新内核源
代码(Linux Kernel)准备好Android 内核驱动程序开发环境。
二. 进入到kernel/common/drivers 目录,新建hello 目录:
linuxidc@www.linuxidc.com:~/Android$ cd kernel/common/drivers
linuxidc@www.linuxidc.com:~/Android/kernel/common/drivers$ mkdir hello
三. 在hello 目录中增加hello.h 文件:
1.#ifndef _HELLO_Android_H_
2.#define _HELLO_ANDROID_H_
3.#include <linux/cdev.h>
4.#include <linux/semaphore.h>
5.#define HELLO_DEVICE_NODE_NAME "hello"
8.#define HELLO_DEVICE_FILE_NAME "hello"
9.#define HELLO_DEVICE_PROC_NAME "hello"
10.#define HELLO_DEVICE_CLASS_NAME "hello"
12.struct hello_android_dev {
13. int val;
14. struct semaphore sem;
15. struct cdev dev;
16.};
17.#endif
这个头文件定义了一些字符串常量宏,在后面我们要用到。此外,还定义了一个字符设备结构体
hello_Android_dev,这个就
是我们虚拟的硬件设备了,val 成员变量就代表设备里面的寄存器,它的类型为int,sem 成员变量是一个
信号量,是用同步
- 3 - ANDROID
自学精品系列——驱动篇
访问寄存器val 的,dev 成员变量是一个内嵌的字符设备,这个Linux 驱动程序自定义字符设备结构体的标
准方法。
四.在hello 目录中增加hello.c 文件,这是驱动程序的实现部分。驱动程序的功能主要是向上层提供访问设
备的寄存器的值,
包括读和写。这里,提供了三种访问设备寄存器的方法,一是通过proc 文件系统来访问,二是通过传统的
设备文件的方法来
访问,三是通过devfs 文件系统来访问。下面分段描述该驱动程序的实现。
首先是包含必要的头文件和定义三种访问设备的方法:
1.#include <linux/init.h>
2.#include <linux/module.h>
3.#include <linux/types.h>
4.#include <linux/fs.h>
5.#include <linux/proc_fs.h>
6.#include <linux/device.h>
7.#include <asm/uaccess.h>
8.
9.#include "hello.h"
10.
11./*主设备和从设备号变量*/
12.static int hello_major = 0;
13.static int hello_minor = 0;
14.
15./*设备类别和设备变量*/
16.static struct class* hello_class = NULL;
17.static struct hello_Android_dev* hello_dev = NULL;
18.
19./*传统的设备文件操作方法*/
20.static int hello_open(struct inode* inode, struct file* filp);
21.static int hello_release(struct inode* inode, struct file* filp);
22.static ssize_t hello_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos);
23.static ssize_t hello_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos);
24.
25./*设备文件操作方法表*/
26.static struct file_operations hello_fops = {
27. .owner = THIS_MODULE,
28. .open = hello_open,
29. .release = hello_release,
30. .read = hello_read,
31. .write = hello_write,
32.};
33.
34./*定义设备属性*/
35.static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store);
36.
- 4 - ANDROID
自学精品系列——驱动篇
37./*访问设置属性方法*/
38.static ssize_t hello_val_show(struct device* dev, struct device_attribute* attr, char* buf);
39.static ssize_t hello_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count);
定义传统的设备文
件访问方法,主要是定义hello_open、hello_release、hello_read 和hello_write 这四个打开、释放、读和写
设备文件的方法:
1./*打开设备方法*/
2.static int hello_open(struct inode* inode, struct file* filp) {
3. struct hello_Android_dev* dev;
4.
5. /*将自定义设备结构体保存在文件指针的私有数据域中,以便访问设备时拿来用*/
6. dev = container_of(inode->i_cdev, struct hello_android_dev, dev);
7. filp->private_data = dev;
8.
9. return 0;
10.}
11.
12./*设备文件释放时调用,空实现*/
13.static int hello_release(struct inode* inode, struct file* filp) {
14. return 0;
15.}
16.
17./*读取设备的寄存器val 的值*/
18.static ssize_t hello_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos) {
19. ssize_t err = 0;
20. struct hello_android_dev* dev = filp->private_data;
21.
22. /*同步访问*/
23. if(down_interruptible(&(dev->sem))) {
24. return -ERESTARTSYS;
25. }
26.
27. if(count < sizeof(dev->val)) {
28. goto out;
29. }
30.
31. /*将寄存器val 的值拷贝到用户提供的缓冲区*/
32. if(copy_to_user(buf, &(dev->val), sizeof(dev->val))) {
33. err = -EFAULT;
34. goto out;
35. }
36.
37. err = sizeof(dev->val);
38.
- 5 - ANDROID
自学精品系列——驱动篇
39.out:
40. up(&(dev->sem));
41. return err;
42.}
43.
44./*写设备的寄存器值val*/
45.static ssize_t hello_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos) {
46. struct hello_android_dev* dev = filp->private_data;
47. ssize_t err = 0;
48.
49. /*同步访问*/
50. if(down_interruptible(&(dev->sem))) {
51. return -ERESTARTSYS;
52. }
53.
54. if(count != sizeof(dev->val)) {
55. goto out;
56. }
57.
58. /*将用户提供的缓冲区的值写到设备寄存器去*/
59. if(copy_from_user(&(dev->val), buf, count)) {
60. err = -EFAULT;
61. goto out;
62. }
63.
64. err = sizeof(dev->val);
65.
66.out:
67. up(&(dev->sem));
68. return err;
69.}
定义通过devfs 文件系统访问方法,这里把设备的寄存器val 看成是设备的一个属性,通过读写这个属性来
对设备进行访问,
主要是实现hello_val_show 和hello_val_store 两个方法,同时定义了两个内部使用的访问val 值的方法
__hello_get_val 和
__hello_set_val:
1. /*读取寄存器val 的值到缓冲区buf 中,内部使用*/
2. static ssize_t __hello_get_val(struct hello_Android_dev* dev, char* buf) {
3. int val = 0;
4.
5. /*同步访问*/
6. if(down_interruptible(&(dev->sem))) {
7. return -ERESTARTSYS;
8. }
剩余29页未读,继续阅读
ryan_hc
- 粉丝: 2
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 收起
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
会员权益专享
最新资源
- zigbee-cluster-library-specification
- JSBSim Reference Manual
- c++校园超市商品信息管理系统课程设计说明书(含源代码) (2).pdf
- 建筑供配电系统相关课件.pptx
- 企业管理规章制度及管理模式.doc
- vb打开摄像头.doc
- 云计算-可信计算中认证协议改进方案.pdf
- [详细完整版]单片机编程4.ppt
- c语言常用算法.pdf
- c++经典程序代码大全.pdf
- 单片机数字时钟资料.doc
- 11项目管理前沿1.0.pptx
- 基于ssm的“魅力”繁峙宣传网站的设计与实现论文.doc
- 智慧交通综合解决方案.pptx
- 建筑防潮设计-PowerPointPresentati.pptx
- SPC统计过程控制程序.pptx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功