Android驱动例子(LED灯控制)

本例子,讲述在Android2.1上完全自已开发一个驱动去控制硬件口并写应用测试该驱动,通过这样一个例子,解析android下的驱动开发流程的应用调用流程,可以说是很好的入门引导

要达到的效果:通过android的应用,调用驱动程序,在开发板上控制4个LED的亮灭。

一、硬件原理

clip_image001

如上图,通过4个IO口控制这LED,低电平LED亮,

这4个IO口分别是GPM1, GPM2, GPM3, GPM4,

二、驱动程序

1、在kernel文件夹下的driver目录,新键驱动文件夹

# cd kernel_android_2.6.28.6/drivers

进到开发板的kernel目录,建驱动文件夹

#mkdir ledtest

2、在/driver/ledtest目录下,新建leddriver.c ,leddriver.h , Kconfig, Makefile 等4个文件

leddriver.c

leddriver.c

#include <linux/kernel.h> #include <linux/sched.h> #include <linux/timer.h> #include <linux/init.h>            /* For __init/__exit/... */ #include <linux/module.h> #include <mach/hardware.h> #include <asm/io.h> #include <asm/uaccess.h> #include <plat/gpio-cfg.h> #include <plat/regs-clock.h> #include <plat/regs-lcd.h> #include <plat/regs-gpio.h> #include <mach/map.h> #include <linux/gpio.h> #include <plat/gpio-bank-m.h> #include <linux/cdev.h> #include <linux/fs.h> //for register_chrdev() #include <linux/device.h> #include <mach/map.h> #include "leddriver.h" #include <linux/miscdevice.h>        /* For MODULE_ALIAS_MISCDEV                             (WATCHDOG_MINOR) */ #include <linux/watchdog.h>        /* For the watchdog specific items */ #include <linux/fs.h>            /* For file operations */ #define Viberator_MAJOR        97  //?÷éè±?o? #define SCULL_NR_DEVS           4 #define SCULL_QUANTUM         4000 #define SCULL_QSET             1000 //---do as the GIO driver #define DEVCOUNT                4 #define GIO_MINOR            2    /* GIO minor no. */ static dev_t dev;        //éê ?? μ?μ??÷ éè±? o? static struct cdev *cdev_p; static int openCnt; //--è???±?á?------------ int VIB_major  = 97;//we asigment it for test int VIB_minor = 0; int VIB_nr_devs = SCULL_NR_DEVS; int VIB_quantum = SCULL_QUANTUM; int VIB_qset = SCULL_QSET;   static struct class *vib_dev_class; #define GPNCON  S3C64XX_GPNCON #define GPNDAT  S3C64XX_GPNDAT #define GPNPUD  S3C64XX_GPNPUD #define GPMCON S3C64XX_GPMCON #define GPMDAT  S3C64XX_GPMDAT #define GPMPUD S3C64XX_GPMPUD   #define VIB_ON 0x11   #defineVIB_OFF 0x22 static const struct file_operations GPIO_Viberator_ctl_ops={     .owner        = THIS_MODULE,     .open    = GPIO_VIB_open,     .read    =GPIO_VIB_read,     .write    =GPIO_VIB_write,     .ioctl     = GPIO_VIB_ioctl,     .release     =GPIO_VIB_release, }; ssize_t GPIO_VIB_read(struct file * file,char * buf,size_t count,loff_t * f_ops) {     printk(" GPIO_VIB_read \r\n");     gpio_direction_output(S3C64XX_GPM(3), 0);//     return count ; } ssize_t GPIO_VIB_write (struct file * file,const char * buf, size_t count,loff_t * f_ops) {       printk(" GPIO_VIB_write \r\n");       gpio_direction_output(S3C64XX_GPM(3), 1);//    return count; }   //ssize_t GPIO_VIB_ioctl(struct inode *  inode,struct file * file,unsigned int cmd, long data) static int GPIO_VIB_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {     printk(KERN_ERR"VIB:GPIO_VIB_ioctl --CMD=%x \n",cmd);     switch(cmd)         {            case VIB_ON:             gpio_direction_output(S3C64XX_GPM(1), 0);//             gpio_direction_output(S3C64XX_GPM(2), 0);//             gpio_direction_output(S3C64XX_GPM(3), 0);//             gpio_direction_output(S3C64XX_GPM(4), 1);//             printk(KERN_ERR"VIB:GPIO_VIB_ioctl --VIB_ON\n");             break;          case VIB_OFF:             {             printk(KERN_ERR"VIB:GPIO_VIB_ioctl --VIB_OFF\n");             gpio_direction_output(S3C64XX_GPM(1), 1);//             gpio_direction_output(S3C64XX_GPM(2), 1);//             gpio_direction_output(S3C64XX_GPM(3), 1);//             gpio_direction_output(S3C64XX_GPM(4), 0);//             break;          }          default:break;                      }         //gpio_free(S3C64XX_GPN(7)); } ssize_t GPIO_VIB_open(struct inode * inode,struct file * file) { //?£?éêy   //MOD_INC_USE_COUNT;   printk("GPIO_VIB_open() \n");      return 0; } ssize_t GPIO_VIB_release(struct inode * inode, struct file * file) {    // MOD_DEC_USE_COUNT;//?£?éêy??      printk("GPIO_VIB_release() \n");        return 0; } static int GPIO_VIB_CTL_init(void) {     int ret  = -ENODEV;    int error ;     printk("---------------------------------------------- \r\n");     //3?ê??ˉ???ú         s3c_gpio_cfgpin(S3C64XX_GPM(1), S3C_GPIO_SFN(1));//GPM1 output         s3c_gpio_cfgpin(S3C64XX_GPM(2), S3C_GPIO_SFN(1));//GPM2 output         s3c_gpio_cfgpin(S3C64XX_GPM(3), S3C_GPIO_SFN(1));//GPM3 output         s3c_gpio_cfgpin(S3C64XX_GPM(4), S3C_GPIO_SFN(1));//GPM4 output #if 1 /*?2ì?·?ê?×¢2á?y?ˉ*/ ret = register_chrdev(Viberator_MAJOR, "viberator", &GPIO_Viberator_ctl_ops); if (ret < 0) {     printk(KERN_ERR "VIB: unable to get major %d\n", ret);     return ret; } //′′?¨\uc1class vib_dev_class = class_create(THIS_MODULE, "viberator"); if (IS_ERR(vib_dev_class)) {     unregister_chrdev(Viberator_MAJOR, "capi20");     return PTR_ERR(vib_dev_class); } //′′?¨?úμ?£? device_create(vib_dev_class, NULL, MKDEV(Viberator_MAJOR, 0), NULL, "vib"); // create a point under /dev/class/vib   //í¨1yé????aá?2?£??y?ˉ?ó??oó£??í?á?ú/dev/class/????éú3é\uc1vib?úμ?£?ó|ó?3ìDò?éò???2ù×÷???t???ù2ù×÷?a???úμ?£?í¨1y\uc1open ,write,read μèoˉêy2ù×÷£??ê?é?éò??′oó??μ?ó|ó?ê?ày3ìDò?£   return 0;     #endif #if 0/* ×¢2á?ˉì?*/     if ((error = alloc_chrdev_region(&dev, 0, DEVCOUNT, "vibrate")) < 0)         {         printk(KERN_ERR                "VIB: Couldn't alloc_chrdev_region, error=%d\n",                error);         return 1;     }          printk("dev = %d  \n",dev);     cdev_p = cdev_alloc();     cdev_p->ops = &GPIO_Viberator_ctl_ops;     error = cdev_add(cdev_p, dev, DEVCOUNT);     if (error) {         printk(KERN_ERR                "VIB: Couldn't cdev_add, error=%d\n", error);         return 1;     }       vib_dev_class = class_create(THIS_MODULE, "vib-dev");     if (IS_ERR(vib_dev_class)) {         res = PTR_ERR(vib_dev_class);         goto out_unreg_class;     }     return 0; #endif out_unreg_class:     class_destroy(vib_dev_class); return 1; }   static int __init S3C6410_VIB_init(void) {     int ret = -ENODEV;     //μ÷ó?oˉêy            printk(KERN_ERR "Auly: S3C6410_VIB_init---\n");     ret = GPIO_VIB_CTL_init();     if(ret)         {         printk(KERN_ERR "Auly: S3C6410_VIB_init--Fail !!!\n");         return ret;     }     return 0; } static void __exit cleanup_GPIO_VIB(void) {     //×¢?úéè±?   //  devfs_unregister_chrdev(Viberator_MAJOR,"gpio_vib_ctl"); #if 0       cdev_del(cdev_p);     unregister_chrdev_region(dev, DEVCOUNT);     class_destroy(vib_dev_class); #endif device_destroy(vib_dev_class, MKDEV(Viberator_MAJOR, 0)); class_destroy(vib_dev_class); unregister_chrdev(Viberator_MAJOR, "viberator"); } MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Peter first driver"); MODULE_ALIAS_CHARDEV(Viberator_MAJOR, 0);   module_init(S3C6410_VIB_init); module_exit(cleanup_GPIO_VIB);

linux

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwxjwz.html