[日期:2011-04-13] | 来源:Linux社区 作者:ok138ok |
本例子,讲述在 2.1上完全自已开发一个驱动去控制硬件口并写应用测试该驱动,通过这样一个例子,解析android下的驱动开发流程的应用调用流程,可以说是很好的入门引导
要达到的效果:通过的应用,调用驱动程序,在开发板上控制4个LED的亮灭。
一、硬件原理
如上图,通过4个IO口控制这LED,低电平LED亮,
这4个IO口分别是GPM1, GPM2, GPM3, GPM4,
二、驱动程序
1、在kernel文件夹下的driver目录,新键驱动文件夹
# cd kernel__2.6.28.6/drivers
进到开发板的kernel目录,建驱动文件夹
2、在/driver/ledtest目录下,新建leddriver.c ,leddriver.h , Kconfig, Makefile 等4个文件
leddriver.c
- #include <linux/kernel.h>
- #include <linux/sched.h>
- #include <linux/timer.h>
- #include <linux/init.h>
- #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>
- #include <linux/watchdog.h>
- #include <linux/fs.h>
- #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
- 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
- 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
- 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);