本文转载自:http://www.cnblogs.com/pengdonglin137/p/3857724.html
基于TINY4412的Andorid开发-------简单的LED灯控制
参考资料:
《Andriod系统源代码情景分析》
《嵌入式Linux系统开发完全手册_基于4412_上册》
作者:彭东林
平台介绍:
主机:Win7 32位
虚拟机:VMware10 + ubuntu-12.04.2-desktop-amd64
Android版本: android-4.2.2_r1
Linux内核版本:linux-3.5.0
Bootloader: 友善之臂提供的Superboot4412.bin
目标平台:tiny4412ADK+S700 4GB Flash
目的: 在Tiny4412上运行的Android系统上,通过点击屏幕上的Button来控制Tiny4412的核心板上的四个LED灯的亮灭。一个有八个Button,每个灯的亮灭通过两个灯来控制,点击ON,相应的LED亮;点击OFF,相应的LED灯灭。
下面分几步完成:
1、编写驱动程序
2、测试驱动程序
3、编写HAL代码
4、编写framework代码
5、编写JNI代码
6、编写App
下面开始:
一、编写驱动程序
分析tiny4412的原理图,看一下LED灯的位置:
可以知道,LED是低电平亮,高电平灭。
看一下,接到了Exynos4412的哪些引脚上了:
可以看到:
LED1 --------- GPM4_0
LED2 --------- GPM4_1
LED3 --------- GPM4_2
LED4 --------- GPM4_3
看一下Exynos4412的芯片手册,看一下GPM4的相关寄存器:
图中第二列表示的相对于基地址的偏移量,这里基地址是:0x11000000.
在芯片手册的Page288 ~ Page291对这些寄存器有更详细的介绍。
以GPM4_0引脚为例:
为了控制灯,[3:0]应设置为0x01,即输出模式
向GPM4DAT的第0位写0,GPM4_0引脚输出低电平,LED1亮;
向GPM4DAT的第0位写1,GPM4_0引脚输出高电平,LED1灭;
接下来,开始写驱动程序,用友善之臂自带的Linux3.5.0内核
1: cd linux-3.5/
2: cd drivers/
3: mkdir android_led
4: cd android_led/
在android_led/下创建led_demo.c和led_demo.h文件:
touch led_demo.c led_demo.h
再在其中创建Makefile和Kconfig文件
touch Makefile Kconfig
- 修改Kconfig:
1: config LED_DEMO
2: tristate "Android Led Demo"
3: default n
4: help
5: This is the led demo for Android system.
- 修改Makefile:
obj-$(CONFIG_LED_DEMO) += led_demo.o
- 修改drivers/Kconfig,添加 source “drivers/android_led/Kconfig”
1: menu "Device Drivers"
2:
3: source "drivers/android_led/Kconfig"
4:
5: ......
6:
7: endmenu
- 修改drivers/Makefile:
1: ......
2:
3: obj-$(CONFIG_LED_DEMO) += android_led/
- 在内核顶层目录下执行make menuconfig,进入Device Drivers,将 Android Led Demo选择为*,然后保存配置退出。
注:执行上面这些操作之前,确保已经按照友善之臂的手册,成功编译了Android上用的Linux内核,并且在arch/arm/boot下生成了zImage等文件。
在前期开发的时候,时不时要编译,可以将drivers/android_led/Makefile修改为:
1: #obj-$(CONFIG_LED_DEMO) += led_demo.o
2: obj-m += led_demo.o
编译的时候,可以使用:
make M=drivers/android_led modules
目的是提高编译速度,最后再将Makfile改回原样。临时测试,可以在Wind7的命令行下,使用adb push将led_demo.ko上传到/data/local下,然后用adb shell登陆板子,进行测试。
- 修改led_demo.h和led_demo.c
led_demo.h:
1: #ifndef __LED_DEMO_H__
2: #define __LED_DEMO_H__
3:
4: #include <linux/cdev.h>
5:
6: #define LED_ON _IOW('L', 0, int)
7: #define LED_OFF _IOW('L', 1, int)
8:
9: #define LED_DEMO_DEVICE_NODE_NAME "led_demo"
10: #define LED_DEMO_DEVICE_CLASS_NAME "led_demo"
11: #define LED_DEMO_DEVICE_FILE_NAME "led_demo"
12:
13: #define EXYNOS4412_GPM4CON 0x110002E0
14: #define EXYNOS4412_GPM4DAT 0x110002E4
15:
16:
17: struct led_demo_dev
18: {
19: struct cdev dev;
20: };
21:
22: #endif
led_demo.c:
1: #include <linux/kernel.h>
2: #include <linux/module.h>
3: #include <linux/fs.h>
4: #include <linux/slab.h>
5: #include <linux/device.h>
6:
7: #include <asm/io.h>
8: #include <asm/uaccess.h>
9:
10:
11: #include "led_demo.h"
12:
13:
14: MODULE_LICENSE("GPL");
15:
16:
17: static int led_demo_major;
18: static int led_demo_minor;
19: static int number_of_dev = 1;
20:
21: static struct led_demo_dev *led_dev = NULL;
22:
23: static unsigned int *GPM4CON = NULL;
24: static unsigned int *GPM4DAT = NULL;
25:
26: static struct class *led_demo_class = NULL;
27:
28:
29: static int led_open (struct inode *node, struct file *fops)
30: {
31: struct led_demo_dev *dev;
32:
33: dev = container_of(node->i_cdev, struct led_demo_dev, dev);
34:
35: fops->private_data = dev;
36:
37: return 0;
38: }
39: static int led_close (struct inode *node, struct file *fops)
40: {
41: return 0;
42: }
43:
44: static long led_ioctl (struct file *fops, unsigned int cmd, unsigned long data)
45: {
46: //struct led_demo_dev * led_dev = (struct led_demo_dev *)fops->private_data;
47:
48: if((data < 1) || (data > 4))
49: {
50: printk(KERN_ALERT"parameter is no valid.\n");
51: return -EINVAL;
52: }
53: