• 字符设备驱动之按键驱动(中断)


    单片机下中断处理过程:

    ①按键按下

    CPU发生中断,跳转到异常向量入口

    ③跳转到中断处理函数

    a、保存被中断的现场

    b、执行中断处理函数

    c、恢复被中断现场

       

    Linux下中断处理过程:

    ARM架构CPU的异常向量地址可以是0x00000000,也可以是0xFFFF0000Linux内核使用的是0xFFFF00000xFFFF0000是一个虚拟地址)。因此,在建立虚拟地址映射之后,需要把异常向量复制到虚拟地址0xFFFF0000上去,Linux使用trap_init函数。

     

    函数接口:

    注册中断:

    1 int request_irq(unsigned int irq, irq_handler_t handler,
    2                 unsigned long irqflags, const char *devname, void *dev_id)

    参数说明:

    irq: 中断号

    handle: 处理函数

    irqflag: 触发方式

    devname: 中断名字

    dev_id: 设备号(用户自定义)

       

    ①分配了一个irqaction结构

    setup_irq(irq, action);

       

    卸载中断:

    1 void free_irq(unsigned int irq, void *dev_id)

    参数说明:

    irq: 中断号

    dev_id: 设备号

    ①根据dev_id,删除用户注册的中断处理函数(释放irqaction结构)

    ②当当前中断号下无irqaction结构时,禁止中断

       

    一些常用的命令:

    cat /proc/devices //查看设备

    cat /proc/interrupts //查看中断

    exec 5</dev/myKey //打开设备

    exec 5<&- //关闭设备

       

    实例:

    driver.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/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
    14 static int major;
    15
    16 static struct class *myKey_class;
    17 static struct class_device *myKey_class_dev;
    18
    19 volatile unsigned long *gpfcon;
    20 volatile unsigned long *gpfdat;
    21
    22 volatile unsigned long *gpgcon;
    23 volatile unsigned long *gpgdat;
    24
    25 static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
    26 static volatile int ev_press = 0;
    27
    28
    29 static unsigned char keyVal = 0;
    30
    31 struct pin_desc {
    32         unsigned int pin;
    33         unsigned int key_val;
    34 };
    35
    36 /*
    37 * 按键按下键值为0x01,...; 松开键值为0x81,...
    38 */
    39 struct pin_desc pins_desc[3] = {
    40         {S3C2410_GPF0, 0x01},
    41         {S3C2410_GPF2, 0x02},        
    42         {S3C2410_GPG11, 0x03},        
    43 };
    44
    45
    46 static int myKey_open(struct inode *inode, struct file *file);
    47 static int myKey_close(struct inode *, struct file *);
    48 static ssize_t myKey_read(struct file *file, char __user *buf, size_t size, loff_t *ppos);
    49
    50
    51 static struct file_operations myKey_fops = {
    52         .open = myKey_open,
    53         .read = myKey_read,
    54         .owner = THIS_MODULE,
    55         .release = myKey_close,
    56 };
    57
    58
    59 static irqreturn_t handle_buttons(int irq, void *dev)
    60 {
    61         unsigned int kval;
    62         struct pin_desc *pinDesc = dev;
    63
    64         kval = s3c2410_gpio_getpin(pinDesc->pin);
    65         if (kval)         //松开
    66         {
    67                 keyVal = 0x80 | pinDesc->key_val;
    68         }
    69         else { //按下
    70                 keyVal = pinDesc->key_val;
    71         }
    72
    73         //唤醒休眠进程
    74         ev_press = 1;        //中断发生标志
    75         wake_up_interruptible(&button_waitq);
    76
    77         return IRQ_RETVAL(IRQ_HANDLED);
    78 }
    79
    80
    81 static int myKey_open(struct inode *inode, struct file *file)
    82 {
    83         request_irq(IRQ_EINT0, handle_buttons, IRQT_BOTHEDGE, "S2", &pins_desc[0]);
    84         request_irq(IRQ_EINT2, handle_buttons, IRQT_BOTHEDGE, "S3", &pins_desc[1]);
    85         request_irq(IRQ_EINT19, handle_buttons, IRQT_BOTHEDGE, "S5", &pins_desc[2]);
    86         
    87         return 0;
    88 }
    89
    90
    91 static int myKey_close(struct inode *inode, struct file *file)
    92 {
    93         free_irq(IRQ_EINT0, &pins_desc[0]);
    94         free_irq(IRQ_EINT2, &pins_desc[1]);
    95         free_irq(IRQ_EINT19, &pins_desc[2]);
    96
    97         return 0;
    98 }
    99
    100
    101 static ssize_t myKey_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
    102 {
    103         //无中断进入休眠
    104         wait_event_interruptible(button_waitq, ev_press);
    105
    106         ev_press = 0;        //清除中断发生标志
    107         copy_to_user(buf, &keyVal, 1);
    108         return 0;
    109 }
    110
    111 static int __init myKey_init(void)
    112 {
    113         /* 物理地址映射成虚拟地址 */
    114         gpfcon = (volatile unsigned long*)ioremap(0x56000050, 16);
    115         gpfdat = gpfcon + 1;
    116
    117         gpgcon = (volatile unsigned long*)ioremap(0x56000060, 16);
    118         gpgdat = gpgcon + 1;
    119
    120         major = register_chrdev(0, "myKey", &myKey_fops);
    121         
    122         myKey_class = class_create(THIS_MODULE, "myKeyclass");
    123         myKey_class_dev = class_device_create(myKey_class, NULL, MKDEV(major, 0), NULL, "myKey");
    124
    125         return 0;
    126 }
    127
    128 static void __exit myKey_exit(void)
    129 {
    130         /* 释放虚拟地址映射 */
    131         iounmap(0x56000050);
    132         iounmap(0x56000060);
    133
    134         unregister_chrdev(major, "myKey");
    135
    136         class_device_unregister(myKey_class_dev);
    137         class_destroy(myKey_class);
    138         return;
    139 }
    140
    141 module_init(myKey_init);
    142 module_exit(myKey_exit);
    143
    144 MODULE_LICENSE("GPL");

       

    app.c

    1 #include <sys/types.h>
    2 #include <sys/stat.h>
    3 #include <fcntl.h>
    4 #include <stdio.h>
    5
    6 int main (void)
    7 {
    8         int fd;
    9         unsigned char keyVal;
    10         ssize_t rst;
    11         
    12         printf("test app! ");
    13
    14         fd = open("/dev/myKey", O_RDWR);
    15         if(fd < 0)
    16         {
    17                 printf("open failed! %d ", fd);
    18                 return -1;
    19         }
    20         
    21         while(1)
    22         {
    23                 rst = read(fd, &keyVal, 1);
    24                 if (rst < 0)
    25                 {        
    26                         printf("read failed! ");
    27                         continue;
    28                 }
    29                 printf("keyVal 0x%x ", keyVal);
    30         }
    31         return 0;        
    32 }

       

    Makefile

    1 KERN_DIR = /work/system/linux-2.6.22.6
    2
    3 all:
    4         make -C $(KERN_DIR) M=`pwd` modules
    5

    6 clean:
    7         make -C $(
    KERN_DIR) M=`pwd` modules clean
    8         rm -rf modules.order

    9

    10 obj-m += myKey_irq.o

  • 相关阅读:
    aidl 详解
    为什么我选择用 flutter
    hunting
    Dynamic programming
    android 微信开发交流群
    hash function 字符串哈希函数
    函数也可以看成是空间的变换
    语法树
    生活中的物理随处可见
    about coroutine
  • 原文地址:https://www.cnblogs.com/lilto/p/11878157.html
Copyright © 2020-2023  润新知