《Android深度探索卷一》读书笔记九
1.LED驱动实现原理
2.编写LED驱动
LED 驱动以动态驱动模块( .ko文件)的形式。LED驱动会建立一个“/dev/开发板型号_leds”设备文件,该Linux驱动可以控制4个LED。向开发板发送长度为1到4的字符串可以控制这4个LED的开关。l表示开、0表示关。如果字符串长度不足4个,相当于后面补0。
(1).创建一个设备文件步骤:
第 1 步:使用 cdev_init 函数初始化 cdev;
如果在一个Linux驱动中要建立多个设备文件,cdev.count变量的值就是要建立的设备文件数。设备文件对应的cdev结构体通过cdev.list.prev和cdev.list. next指针变量连接。从而形成了一个双向链表。
第 2 步s 指定设备号;
Linux 设备文件的设备号分为主设备号和次设备号。用1个int类型(dev_t)表示。其中前12位表示主设备号,后20位表示次设备号。有两种指定方法:直接在代码中指定(硬编码);动态分配。多个Lihux设备文件可以拥有同一个主设备号。但两个设备的主设备号和次设备号不能都一样。
使用registe_chrdev_region函数注册字符设备区域。需要 MKDEV宏将主设备号和次设备号组合成设备号。使用 MAJOR和 MINOR宏从设备号中可获取主设备号和次设备号。
第 3步:使用 cdev_add函数将字符设备添加到内核中的字符设备数组中;
cdev_add函数用于将字符设备添加到probes数组(保存己建立的字符设备)中。
第 4 步:使用 class_create宏创建 struct class;
struct class包含了一些与设备文件有关的变量以及一些回调函数指针变量。
第 5 步:使用device_create函数创建设备文件;
(2).在编写leds_create_device函数时应了解:
① DEVICE_COUNT表示建立设备文件的个数。
② alloc_chrdev_region函数的第2个参数表示分配的起始次设备号。
③ 采用自动分配设备号的方式创建设备文件,使用MAJOR和MINOR宏获取主设备号和次设备号,并分别保存在major和minor变量中。
④ LED驱动的设备号保存在dev_numbe变量中。需要将led_cdev.dev变量的值赋给dev_number。
(3).卸载 LED 驱动的设备文件
卸载Linux驱动的设备文件需要依次调用device_destroy、class_destroy和unregister_chrdev_region方法。
led_destroy_device函数用于卸载LED驱动的设备文件,leds_exit函数是LED 驱动的卸载函数。leds_exit函数通过调用leds_destroy_device函数来卸载LED驱动设备文件。
(4).设置寄存器与初始化LED驱动
在控制LED亮、灭之前必须要了解如何设置寄存器。ARM处理器有多个寄存器,通过设置不同寄存器的值。可以设置LED引脚的状态、打开或禁止上拉(pull-up)电路以及控制LED的亮和灭。控制LED需要通过3个寄存器来完成;每一个寄存器可以使用4个字节,也就是一个int类型数据占用的空间;LED有两个引脚:GPBO和GPBI,使用GPMCON寄存器的低16位将LED的两个端口的属性设为Output,每4位设置一个LED,共4个LED;使用GPMDAT寄存器的低4位控制4个LED的亮、灭;使用GPMPUD寄存糕的低8位分别打开4个LED的上拉(pull-up)电路。每两位控制一个LED的上拉电路。
(5).控制 LED
LED 驱动可以使用两种方式控制 LED:通过字符串控制;通过 l/0命令控制。LED驱动必须要接收相应的数据才能使用上述两种方式控制LED。如果通过字符串控制LED,需要使用fife_operations.write函数。如果通过I/0命令控制 LED,需要使用file__operations.ioctl函数。4个LED的状态(亮、灭)用一个长度为4的char数组(mem)存储。ioread32, iowrite32用于读写虚拟地址中的数据。这两个函数用于读写32位的数据。
(6).LED 驱动的模块参数
为Linux驱动指定一个模块参数需要使用module_param(name, type, perm)宏。其中name表示参数名,type表示参数类型,perm表示读/写权限。
使用 module_ param_array(name, type, nump, perm)宏可以为 Linux 驱动指定数组形式的模块参数。其中name表示参数名,type表示数组元素的数据类型, nump表示存储数组长度的变量的指针,perm表示参数文件的访问权限。
(7).测试LED驱动
编写测试 I/0 控制命令的通用程序。LED 驱动有两种与设备文件交互的方式:直接写入字符串数据和I/O控制命令。直接向设备文件写入数据可以使用命令行方式来完成,也可以通过 write 函数来完成。但 I/0 控制命令只能通过ioctl函数发出。
(8).LED驱动的移植
Android 系统能否正常运行,在很大程度上取决于Android 能否识别当前设备的硬件,识别这些设备的工作主要由 Linux 驱动完成。而 Linux 驱动必须要在当前使用的Linux内核下编译才可以安装在当前的Linux或Android系统中。
移植Linux驱动有一条非常重要就是在修改Linux驱动的源代码时应尽量不修改Linux驱动的接口。否则就意味着驱动的接口变化了,这样所有调用Linux驱动的程序都需要进行修改。