现在的位置: 首页 > 综合 > 正文

使用静态设备节点的cdev字符驱动GPIO

2012年09月29日 ⁄ 综合 ⁄ 共 4119字 ⁄ 字号 评论关闭
文件: beep.rar
大小: 21KB
下载: 下载

尽管在2.6的内核版本已经支持udev,可以很方便的使用,并且使用也很舒服。但是使用udev,在启动过程中扫描/sys/class目录并生成设备节点的时间稍微有点长,在一些系统中是无法忍受的,所以没办法只好放弃udev,回到静态设备节点的时代,以加快启动速度。

 
2.6内核中,引入了cdev概念,使用cdev的驱动与传统的2.4的字符驱动又不一样,下面给出一个使用cdev和静态设备节点的驱动范例。
 
beepdrv.c
  1 /* beepdrv.c
  2     beep driver. GUANGZHOU ZHIYUAN
  3 
  4    Copyright (c) 2009 GUANGZHOU ZHIYUAN ELECTRONICS CO.LTD
  5    By Chenxibing <Linux@zlgmcu.com> 
  6 */
  7 
  8 #include <linux/init.h>
  9 #include <linux/module.h>
 10 #include <linux/moduleparam.h>
 11 #include <linux/kernel.h>
 12 #include <linux/fs.h>
 13 #include <linux/errno.h>
 14 #include <linux/device.h>
 15 #include <linux/miscdevice.h>
 16 #include <linux/platform_device.h>
 17 #include <linux/types.h>
 18 #include <linux/io.h>
 19 #include <linux/delay.h>
 20 #include <linux/irq.h>
 21 #include <linux/interrupt.h>
 22 #include <linux/cdev.h>
 23 
 24 #include <asm/arch/hardware.h>
 25 #include <asm/uaccess.h>
 26 #include <asm/arch/irq.h>
 27 #include <asm/io.h>
 28 #include <asm/pgtable.h>
 29 #include <asm/page.h>
 30 
 31 #include <mach/hardware.h>
 32 #include <mach/platform.h>
 33 
 34 #include <asm/arch/lpc32xx_gpio.h>
 35 
 36 #include "beepdrv.h"
 37 
 38 #define DEV_NAME    "beep"
 39 struct cdev *beep_cdev; 
 40 #define BEEP_MAJOR 231
 41 #define BEEP_MINOR 0
 42 int beep_major = BEEP_MAJOR;
 43 int beep_minor = BEEP_MINOR;
 44 
 45 module_param(beep_major, int, 0);
 46 module_param(beep_minor, int, 0);
 47 
 48 #define GPIO_IOBASE io_p2v(GPIO_BASE)
 49 
 50 static struct semaphore beep_sem;
 51 
 52 static int beep_open(struct inode *inode, struct file *filp)
 53 {
 54     __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF
 55 
 56     try_module_get(THIS_MODULE);
 57     printk( KERN_INFO DEV_NAME " opened!\n");
 58     return 0;
 59 }
 60 
 61 static int beep_release(struct inode *inode, struct file *filp)
 62 {
 63     __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF
 64 
 65     module_put(THIS_MODULE);
 66     printk(KERN_INFO DEV_NAME " released!\n");
 67     return 0;
 68 }
 69 
 70 static int beep_ioctl(struct inode *inode, struct file *filp,
 71                         unsigned int cmd, unsigned long arg)
 72 {
 73      int level;
 74 
 75     if (_IOC_TYPE(cmd) != BEEP_IOC_MAGIC) {
 76         return -ENOTTY;
 77     }
 78 
 79     if (_IOC_NR(cmd) >= BEEP_IOC_MAXNR) {
 80         return -ENOTTY;
 81     }
 82 
 83 //    printk("arg=0x%x\n", arg);
 84 
 85 
 86 
 87     switch (cmd) {
 88     case SET_BEEP_ON:
 89         __raw_writel(_BIT(5), GPIO_P3_OUTP_CLR(GPIO_IOBASE));//CLR GPIO_05
 90 
 91         udelay(10);
 92         break;
 93         
 94     case SET_BEEP_OFF:
 95         __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05
 96 
 97         udelay(10);
 98         break;
 99 
100     default:
101         __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05
102 
103         break;
104     }
105 
106     return 0;
107 }
108 
109 static struct file_operations beep_fops = {
110     .owner = THIS_MODULE,
111     .ioctl     = beep_ioctl,
112     .open = beep_open,
113     .release = beep_release,
114 };
115 
116 static void beep_setup_cdev(struct cdev *dev)
117 {
118     int err, devno = MKDEV(beep_major, beep_minor);
119             
120     cdev_init(dev, &beep_fops);
121     dev->owner = THIS_MODULE;
122     dev->ops = &beep_fops;
123     err = cdev_add (dev, devno, 1);
124     /* Fail gracefully if need be */
125     if (err)
126         printk(KERN_NOTICE "Error %d adding gpio.\n", err);
127 }
128 
129 static int __init beep_init(void)
130 {
131     int result;
132     printk(DEV_NAME " init starting......\n");
133 
134     __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF
135 
136 
137     dev_t dev = 0;// MKDEV(gpio_major, 0);
138 
139     /*
140      * Register your major, and accept a dynamic number.
141      */
142     if (beep_major)
143         result = register_chrdev_region(beep_minor, 1, DEV_NAME);
144     else {
145         result = alloc_chrdev_region(&dev, 0, 1, DEV_NAME);
146         beep_major = MAJOR(dev);
147     }
148     if (result < 0)
149         return result;
150  
151     beep_cdev = cdev_alloc();
152     if (!beep_cdev) {
153         result = -ENOMEM;
154         goto fail; /* Make this more graceful */
155     }
156     beep_setup_cdev(&beep_cdev);
157     printk(DEV_NAME " registered OK.\n");
158     return 0;
159 fail:
160     cdev_del(&beep_cdev);
161     unregister_chrdev_region(MKDEV(beep_major, beep_minor), 1); 
162 // beep_exit();
163 
164         return result;
165 }
166 
167 static int __exit beep_exit(void)
168 {
169     cdev_del(&beep_cdev);
170     unregister_chrdev_region(MKDEV(beep_major, beep_minor), 1); 
171     printk(DEV_NAME " unregistered.\n");
172 }
173 
174 
175 module_init(beep_init);
176 module_exit(beep_exit);
177 
178 MODULE_AUTHOR("Abing <Linux@zlgmcu.com>");
179 MODULE_DESCRIPTION("ZHIYUAN tp-beep Driver");
180 MODULE_LICENSE("GPL");

beepdrv.h

 1 #ifndef __BEEPDRV_H
 2 #define __BEEPDRV_H
 3 #include <linux/ioctl.h>
 4 
 5 #define BEEP_IOC_MAGIC     'b'
 6 
 7 #define SET_BEEP_ON     _IO(BEEP_IOC_MAGIC, 0)
 8 #define SET_BEEP_OFF    _IO(BEEP_IOC_MAGIC, 1)
 9 
10 #define BEEP_IOC_MAXNR    2
11 
12 #endif //__BEEPDRV_H

 

抱歉!评论已关闭.