无网不进  
软硬件开发

硬件平台: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目录下

 

[javascript] view plain copy
 
  1. #include <linux/module.h>    
  2. #include <linux/kernel.h>    
  3. #include <linux/fs.h>    
  4. #include <linux/uaccess.h> /* copy_to_user,copy_from_user */    
  5. #include <linux/miscdevice.h>    
  6. #include <linux/device.h>    
  7. #include <asm/io.h>    
  8.     
  9. static struct class  *gpio_class;    
  10.     
  11. volatile unsigned long *DIR;    
  12. volatile unsigned long *DAT;   
  13. volatile unsigned long *CLK;   
  14.     
  15. int gpio_open (struct inode *inode,struct file *filp)    
  16.     
  17. {    
  18.     *CLK = 0x00040002; //Enable  
  19.     *DIR = (*DIR)&0xffffffef;  //output    
  20.     return 0;    
  21. }    
  22.     
  23. ssize_t gpio_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos)    
  24. {    
  25.     return 0;    
  26. }    
  27.     
  28. ssize_t gpio_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)    
  29. {    
  30.     char val_buf[2];    
  31.     int ret;    
  32.     ret = copy_from_user(val_buf,buf,count);    
  33.             
  34.     switch(val_buf[0])    
  35.     {    
  36.         case 0x31 :    
  37.             *DAT = (*DAT)|0x00000010;    
  38.             break;    
  39.         case 0x30 :    
  40.             *DAT = (*DAT)&0xffffffef;           
  41.             break;    
  42.         default :    
  43.             break;    
  44.     }    
  45.     return count;    
  46. }    
  47.     
  48. struct file_operations gpio_fops =    
  49. {    
  50.     .owner   = THIS_MODULE,    
  51.     .open    = gpio_open,    
  52.     .read    = gpio_read,    
  53.     .write   = gpio_write,    
  54. } ;    
  55.     
  56. int major;    
  57. int gpio_init (void)    
  58. {       
  59.         
  60.     major = register_chrdev(0,"Android_gpio",&gpio_fops);    
  61.     gpio_class = class_create(THIS_MODULE, "Android_gpio");    
  62.     device_create(gpio_class,NULL,MKDEV(major,0),NULL,"AdrIO");    
  63.     
  64.     DIR = (volatile unsigned long *)ioremap(0x4804C134,4);    
  65.     DAT = (volatile unsigned long *)ioremap(0x4804C13C,4);    
  66.     CLK = (volatile unsigned long *)ioremap(0x44E000AC,4);  
  67.   
  68.     printk ("gpio is ready\n");    
  69.     return 0;    
  70. }    
  71.     
  72. void gpio_exit (void)    
  73. {    
  74.     unregister_chrdev(major,"Android_gpio");    
  75.     device_destroy(gpio_class,MKDEV(major,0));    
  76.     class_destroy(gpio_class);    
  77.     
  78.     iounmap(DIR);    
  79.     iounmap(DAT);    
  80.     iounmap(CLK);  
  81.     
  82.     printk ("module exit\n");    
  83.     return ;    
  84. }    
  85.     
  86. MODULE_LICENSE("GPL");    
  87. module_init(gpio_init);    
  88. module_exit(gpio_exit);   

打开drivers/char目录下的Makefile,增加:

 

 

[javascript] view plain copy
 
  1. obj-$(CONFIG_ANDROID_GPIO)  += android_gpio.o  

打开drivers/char目录下的Kconfig,增加:

 

 

[javascript] view plain copy
 
  1. config ANDROID_GPIO  
  2.        tristate "android gpio enable"  
  3.        default y  

源码目录下执行:

 

make ARCH=arm CROSS_COMPILE=arm-eabi- uImage

生成uImage,重新启动新系统,ls /dev 查看设备:

 

[javascript] view plain copy
 
  1. # ls /dev                                                        
  2. AdrIO                                                                           
  3. alarm                                                                            
  4. android_adb                                                                  
  5. ashmem                                                                        
  6. binder                                                                           
  7. block                                                                             
  8. bus   

发现AdrIO设备,第一步完成,注意在操作物理地址时一定要对位进行操作,不然

GPIO1会影响到AM335X Starter Kit的LCD显示,下一步就要执行C程序测试该驱动。

posted on 2018-01-10 13:43  无网不进  阅读(1051)  评论(0)    收藏  举报