驱动的分层设计——按键点灯

Posted zhu-g5may

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了驱动的分层设计——按键点灯相关的知识,希望对你有一定的参考价值。

源码附带注释:

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!
");
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]");

 

以上是关于驱动的分层设计——按键点灯的主要内容,如果未能解决你的问题,请参考以下文章

解构领域驱动设计:领域驱动设计的核心之分层架构

ESP 保姆级教程 疯狂点灯篇 —— 案例:ESP8266 + LED + 按键(模拟按键控制电器设备开关)

ESP 保姆级教程 疯狂点灯篇 —— 案例:ESP8266 + LED + 按键 + PWM调整亮度(模拟按键控制灯亮度)

给驱动添加sysfs设备模型(基于中断的按键程序)

DDD领域驱动设计实战-分层架构及代码目录结构

使用中断的按键处理程序,实现按键点灯的功能