硬件平台:TI AM335X Starter Kit
开发源码:TI-Android-ICS-4.0.3-DevKit-EVM-SK-3.0.1.bin
主机系统:Ubuntu 10.04
这次写《Android 从硬件到应用》是想尝试从底层的最简单的GPIO硬件驱动开始,一步一步的向上走,经过硬件抽象层HAL、JNI方法等,最终编写出APP,达到硬件调用的目的,期间会增加一些Android下C程序测试底层驱动的细节。既然是从零编写驱动,那就要脱离源码包里已有的一些api函数,从硬件电路开始。找到EVM板GPIO处原理图:
我要控制LED D1的状态,如上图所示,D1接了Q4,也就是BSS138,N沟道的MOS器件,AM335X_GPIO_LED4为高电平时,Q4的栅极漏极导通,D1为亮,反之,灭。首先设置GPIO时钟:
一、CM_PER_GPIO1_CLKCTRL:地址0x44E000AC 要装载的值为 0x00040002
接着设置GPIO1输出使能:
二、GPIO_OE:地址0x4804C134 要装载的值为 0x0
然后设置输出GPIO1的输出:
三、GPIO_DATAOUT:地址0x4804C13C 要装载的值为 0x00000010或者是0x00000000,让AM335X_GPIO_LED4引脚为高或低,这样D1就可以亮灭
编写驱动程序 android_gpio.c:移到drivers/char目录下
- #include <linux/module.h>
 - #include <linux/kernel.h>
 - #include <linux/fs.h>
 - #include <linux/uaccess.h> /* copy_to_user,copy_from_user */
 - #include <linux/miscdevice.h>
 - #include <linux/device.h>
 - #include <asm/io.h>
 - static struct class *gpio_class;
 - volatile unsigned long *DIR;
 - volatile unsigned long *DAT;
 - volatile unsigned long *CLK;
 - int gpio_open (struct inode *inode,struct file *filp)
 - {
 - *CLK = 0x00040002; //Enable
 - *DIR = (*DIR)&0xffffffef; //output
 - return 0;
 - }
 - ssize_t gpio_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
 - {
 - return 0;
 - }
 - ssize_t gpio_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
 - {
 - char val_buf[2];
 - int ret;
 - ret = copy_from_user(val_buf,buf,count);
 - switch(val_buf[0])
 - {
 - case 0x31 :
 - *DAT = (*DAT)|0x00000010;
 - break;
 - case 0x30 :
 - *DAT = (*DAT)&0xffffffef;
 - break;
 - default :
 - break;
 - }
 - return count;
 - }
 - struct file_operations gpio_fops =
 - {
 - .owner = THIS_MODULE,
 - .open = gpio_open,
 - .read = gpio_read,
 - .write = gpio_write,
 - } ;
 - int major;
 - int gpio_init (void)
 - {
 - major = register_chrdev(0,"Android_gpio",&gpio_fops);
 - gpio_class = class_create(THIS_MODULE, "Android_gpio");
 - device_create(gpio_class,NULL,MKDEV(major,0),NULL,"AdrIO");
 - DIR = (volatile unsigned long *)ioremap(0x4804C134,4);
 - DAT = (volatile unsigned long *)ioremap(0x4804C13C,4);
 - CLK = (volatile unsigned long *)ioremap(0x44E000AC,4);
 - printk ("gpio is ready\n");
 - return 0;
 - }
 - void gpio_exit (void)
 - {
 - unregister_chrdev(major,"Android_gpio");
 - device_destroy(gpio_class,MKDEV(major,0));
 - class_destroy(gpio_class);
 - iounmap(DIR);
 - iounmap(DAT);
 - iounmap(CLK);
 - printk ("module exit\n");
 - return ;
 - }
 - MODULE_LICENSE("GPL");
 - module_init(gpio_init);
 - module_exit(gpio_exit);
 
打开drivers/char目录下的Makefile,增加:
- obj-$(CONFIG_ANDROID_GPIO) += android_gpio.o
 
打开drivers/char目录下的Kconfig,增加:
- config ANDROID_GPIO
 - tristate "android gpio enable"
 - default y
 
源码目录下执行:
make ARCH=arm CROSS_COMPILE=arm-eabi- uImage
生成uImage,重新启动新系统,ls /dev 查看设备:
- # ls /dev
 - AdrIO
 - alarm
 - android_adb
 - ashmem
 - binder
 - block
 - bus
 
发现AdrIO设备,第一步完成,注意在操作物理地址时一定要对位进行操作,不然
GPIO1会影响到AM335X Starter Kit的LCD显示,下一步就要执行C程序测试该驱动。
                    
                
                
            
        
浙公网安备 33010602011771号