[Linux]中断按键
[Linux]中断按键
艾恩凝
2021/4/6
INTRODUCIOTN
利用中断减小资源使用
CODE
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/uaccess.h>
8#include <asm/irq.h>
9#include <asm/io.h>
10#include <asm/arch/regs-gpio.h>
11#include <asm/hardware.h>
12
13#define BUTTON_MAJOR_NUMBER 200
14#define DEVICE_NAME "button_drv"
15
16static struct class *button_drv_class;
17static struct class_device *button_drv_class_dev;
18
19volatile unsigned long *GPFCON;
20volatile unsigned long *GPFDAT;
21
22volatile unsigned long *GPGCON;
23volatile unsigned long *GPGDAT;
24
25static int button_drv_close(struct inode *inode, struct file *file);
26
27static DECLARE_WAIT_QUEUE_HEAD(button_waitq);//register interrupt
28static volatile int ev_press = 0;//interrupt flags,if interrupt will set 1
29
30struct pins_desc{
31 unsigned int pin;
32 unsigned int key_val;
33};
34static unsigned char key_val;
35struct pins_desc pins_descs[4] = {
36 {S3C2410_GPF0, 0x01},
37 {S3C2410_GPF2, 0x02},
38 {S3C2410_GPG3, 0x03},
39 {S3C2410_GPG11, 0x04},
40};
41
42
43static irqreturn_t buttons_irq(int irq, void *dev_id){
44 struct pins_desc * pindesc = (struct pins_desc *)dev_id;
45 unsigned int pinval;
46
47 pinval = s3c2410_gpio_getpin(pindesc->pin);
48
49 if (pinval)
50 {
51 /* 松开 */
52 key_val = 0x80 | pindesc->key_val;
53 }
54 else
55 {
56 /* 按下 */
57 key_val = pindesc->key_val;
58 }
59
60 ev_press = 1; /* interrupt */
61 wake_up_interruptible(&button_waitq); /* wake up */
62
63
64 return IRQ_RETVAL(IRQ_HANDLED);
65}
66
67static int button_drv_open(struct inode *inode,struct file *file){
68 // *GPFCON &= ~((0x3<<(0*2)) | (0x3<<(2*2)));
69 // *GPGCON &= ~((0x3<<(3*2)) | (0x3<<(11*2)));
70 //request_irq(IRQ_EINT0,button_irq,);
71 request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, "S2", &pins_descs[0]);
72 request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, "S3", &pins_descs[1]);
73 request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "S4", &pins_descs[2]);
74 request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, "S5", &pins_descs[3]);
75 return 0;
76}
77
78static ssize_t button_drv_read(struct file *file, const char __user *buf, size_t count, loff_t * ppos){
79 if (count != 1)
80 return -EINVAL;
81 wait_event_interruptible(button_waitq, ev_press);//sleep
82 copy_to_user(buf, &key_val, sizeof(key_val));
83 ev_press = 0;
84 return 1;
85}
86//copy_from_user
87
88static struct file_operations button_drv_fops = {
89 .owner = THIS_MODULE,
90 .open = button_drv_open,
91 .read = button_drv_read,
92 .release = button_drv_close,
93};
94
95static int button_drv_init(void){
96 register_chrdev(BUTTON_MAJOR_NUMBER,DEVICE_NAME, &button_drv_fops);//register tell kernel
97 button_drv_class = class_create(THIS_MODULE, DEVICE_NAME);
98 button_drv_class_dev = class_device_create(button_drv_class, NULL, MKDEV(BUTTON_MAJOR_NUMBER, 0), NULL, DEVICE_NAME);
99
100 GPFCON = (volatile unsigned long *)ioremap(0x56000050, 16);
101 GPFDAT = GPFCON + 1;
102
103 GPGCON = (volatile unsigned long *)ioremap(0x56000060, 16);
104 GPGDAT = GPGCON + 1;
105
106 return 0;
107}
108
109static void button_drv_exit(void){
110 unregister_chrdev(BUTTON_MAJOR_NUMBER, DEVICE_NAME);//unregister tell kernel
111 class_device_unregister(button_drv_class_dev);
112 class_destroy(button_drv_class);
113 iounmap(GPFCON);
114 iounmap(GPGCON);
115}
116static int button_drv_close(struct inode *inode, struct file *file)
117{
118 free_irq(IRQ_EINT0, &pins_descs[0]);
119 free_irq(IRQ_EINT2, &pins_descs[1]);
120 free_irq(IRQ_EINT11, &pins_descs[2]);
121 free_irq(IRQ_EINT19,&pins_descs[3]);
122 return 0;
123}
124
125module_init(button_drv_init);
126module_exit(button_drv_exit);
127MODULE_AUTHOR("https://aeneag.xyz");
128MODULE_VERSION("0.1");
129MODULE_DESCRIPTION("S3C2440 Button Driver");
130MODULE_LICENSE("GPL");
131
CONCLUSION
不想多说话了,代码好写,需要理解东西比较多
吾心信其可行,
则移山填海之难,
终有成功之日!
——孙文
则移山填海之难,
终有成功之日!
——孙文
评论
0 评论