1. 程式人生 > >驅動的分層設計——按鍵點燈

驅動的分層設計——按鍵點燈

move kde probe lease hrd class ive exit signed

源碼附帶註釋:

key_dev.c

 1 #include <linux/module.h>
 2 #include <linux/kernel.h>
 3 #include <linux/fs.h>
 4 #include <linux/init.h>
 5 #include <linux/delay.h>
 6 #include <linux/irq.h>
 7 #include <asm/irq.h>
 8 #include <asm/io.h>
 9 #include <linux/cdev.h>
10
#include <linux/device.h> 11 #include <linux/interrupt.h> 12 #include <linux/input.h> 13 #include <linux/bitmap.h> 14 #include <asm/gpio.h> 15 #include <linux/platform_device.h> 16 17 /*記錄硬件相關資源*/ 18 static struct resource key_rsrc[] = { 19 [0] = { /*內存空間*/ 20 .start = 0x56000050
, 21 .end = 0x56000050 + 8 -1, 22 .flags = IORESOURCE_MEM 23 }, 24 [1] = { 25 /*GPF4,5,6*/ 26 .start = 4, 27 .end = 6, 28 .flags = IORESOURCE_IO //flag隨便取個什麽,按照自己的想法來就行了 29 } 30 }; 31 32 static struct platform_device key_dev = { 33 .name = "
key_led", 34 .num_resources = ARRAY_SIZE(key_rsrc), 35 .resource = key_rsrc 36 }; 37 38 /*之所以要平臺設備要註冊進內核,是因為待會平臺設備要根據平臺name找到相應的設備 39 *然後獲得硬件相關的資源 40 */ 41 static int key_dev_init(void) 42 { 43 /*註冊*/ 44 platform_device_register(&key_dev); 45 return 0; 46 } 47 48 static void key_dev_exit(void) 49 { 50 platform_device_unregister(&key_dev); 51 } 52 53 module_init(key_dev_init); 54 module_exit(key_dev_exit); 55 56 MODULE_LICENSE("GPL"); 57 MODULE_AUTHOR("[email protected]");

key_drv.c

  1 #include <linux/module.h>
  2 #include <linux/kernel.h>
  3 #include <linux/fs.h>
  4 #include <linux/init.h>
  5 #include <linux/delay.h>
  6 #include <linux/irq.h>
  7 #include <asm/irq.h>
  8 #include <asm/io.h>
  9 #include <linux/cdev.h>
 10 #include <linux/device.h>
 11 #include <linux/interrupt.h>
 12 #include <linux/input.h>
 13 #include <linux/bitmap.h>
 14 #include <asm/gpio.h>
 15 #include <linux/platform_device.h>
 16 
 17 static volatile unsigned long *gpfcon;
 18 static volatile unsigned long *gpfdat;
 19 
 20 static struct timer_list key_time;
 21 
 22 static struct class *key_class;
 23 
 24 struct input_inode {
 25             char *name;
 26             unsigned int irq_type;
 27             unsigned int pin;
 28             unsigned int key_num;
 29 };
 30 
 31 static struct input_inode *irq_pd;
 32 static struct resource *key_resource;
 33 static struct resource *pin_resource;
 34 
 35 static struct input_inode key[] = {
 36                  [0] = {
 37                          "EINT0",
 38                          IRQ_EINT0,
 39                          S3C2410_GPF(0),
 40                          0},
 41                  [1] = {
 42                         "EINT2",
 43                          IRQ_EINT2,
 44                          S3C2410_GPF(2),
 45                          1},
 46                  [2] = {
 47                         "EINT11",
 48                         IRQ_EINT11,
 49                         S3C2410_GPG(3),
 50                         2},
 51 };
 52 
 53 static irqreturn_t key_irq(int irq, void *dev_id)
 54 {
 55      irq_pd = (struct input_inode *)dev_id;
 56      mod_timer(&key_time,jiffies + HZ/100); //延遲10ms,延遲過程中斷仍然可以被觸發
 57       
 58       return IRQ_HANDLED;
 59 }
 60 
 61 static void key_time_function(unsigned long data)
 62 {
 63      unsigned int key_val;
 64      unsigned int pin_num;
 65      
 66      if(!irq_pd)
 67          return;
 68 
 69      key_val = s3c2410_gpio_getpin(irq_pd->pin);
 70      pin_num = pin_resource->start + irq_pd->key_num;
 71      
 72      if(key_val){
 73          
 74         (*gpfdat) |= (1<<pin_num);
 75         
 76      }else{
 77      
 78         (*gpfdat) &= ~(1<<pin_num);
 79         
 80      }
 81 }
 82 
 83 int key_open(struct inode *inode, struct file *file)
 84 {
 85     int i;
 86     int pin_num;
 87     pin_num = pin_resource->end - pin_resource->start + 1;
 88     /*配置輸出引腳*/
 89     for(i = 0; i < pin_num; i++){
 90         *gpfcon &= ~(3<<((pin_resource->start + i)* 2));
 91         *gpfcon |= (1<<((pin_resource->start + i)* 2));
 92     }
 93     
 94     return 0;
 95 }
 96 
 97 int key_release(struct inode * inode, struct file * file)
 98 {
 99      return 0;
100 }
101 
102 static int major;
103 
104 static struct file_operations key_fops = {
105            .owner   = THIS_MODULE,
106            .open    = key_open,
107            .release = key_release,
108 };
109            
110 //驅動分離適合用probe函數
111 static int key_probe(struct platform_device *pdev) //需要枚舉找到設備裏面同名的pdev
112 {
113     int i;
114     int error;
115      /*獲得設備裏面的硬件資源*/
116     major = register_chrdev(0,"led_key",&key_fops); //cat /proc/devices 出現led_key
117     key_class = class_create(THIS_MODULE,"key");
118     device_create(key_class,NULL,MKDEV(major,0),NULL,"key0_led"); //次設備號0,/dev/key0_led
119     
120     key_resource = platform_get_resource(pdev, IORESOURCE_MEM,0);
121     gpfcon = ioremap(key_resource->start,key_resource->end-key_resource->start + 1);
122     gpfdat = gpfcon +1;
123 
124     pin_resource = platform_get_resource(pdev, IORESOURCE_IO,0);
125     
126     for(i = 0; i < 3; i++){
127         error = request_irq(key[i].irq_type,key_irq,IRQ_TYPE_EDGE_BOTH,key[i].name,&key[i]);
128         if(error){
129           printk("couldn‘t get irq!\n");
130           return -1;
131         }
132     }
133 
134     init_timer(&key_time);
135     key_time.function = key_time_function;
136     add_timer(&key_time);
137 
138     return 0;
139 }
140 
141 static int __devexit key_remove(struct platform_device *pdev)
142 {
143     int i;
144     del_timer(&key_time);
145     for(i = 0; i < 3; i++){
146       free_irq(key[i].irq_type,&key[i]);
147     }
148     unregister_chrdev(major,"led_key");
149     class_destroy(key_class);
150     device_destroy(key_class, MKDEV(major,0));
151     return 0;
152 }
153 
154 static struct platform_driver key_driver = {
155     .driver = {
156         .name    = "key_led",
157         .owner    = THIS_MODULE,
158     },
159     .probe    = key_probe,
160     .remove    = __devexit_p(key_remove),
161 };
162 
163 static int key_drv_init(void)
164 {
165     /*註冊*/
166     platform_driver_register(&key_driver);
167     return 0;
168 }
169 
170 static void key_drv_exit(void)
171 {
172     platform_driver_unregister(&key_driver);
173 }
174 
175 module_init(key_drv_init);
176 module_exit(key_drv_exit);
177 
178 MODULE_LICENSE("GPL");
179 MODULE_AUTHOR("[email protected]");

驅動的分層設計——按鍵點燈