zoukankan      html  css  js  c++  java
  • 3、JZ2440 按键驱动(中断)

    驱动代码

      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 DEVICE_NAME     "key_dev2"  /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */
     14 
     15 static struct class *key_class;
     16 static struct class_device    *key_class_dev;
     17 
     18 volatile unsigned long *gpfcon;
     19 volatile unsigned long *gpfdat;
     20 
     21 volatile unsigned long *gpgcon;
     22 volatile unsigned long *gpgdat;
     23 
     24 /* 创建以个等待队列头 */
     25 static DECLARE_WAIT_QUEUE_HEAD(key_waitq);
     26 
     27 /* 中断事件标志, 中断服务程序将它置1,third_drv_read将它清0 */
     28 static volatile int ev_press = 0;
     29 
     30 struct pin_desc{
     31     unsigned int pin;
     32     unsigned int key_val;
     33 };
     34 /* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 */
     35 /* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 */
     36 static unsigned char key_val;
     37 
     38 struct pin_desc pins_desc[4] = {
     39     {S3C2410_GPF0, 0x01},
     40     {S3C2410_GPF2, 0x02},
     41     {S3C2410_GPG3, 0x03},
     42     {S3C2410_GPG11, 0x04},
     43 };
     44 
     45 /*
     46   * 确定按键值
     47   */
     48 static irqreturn_t keys_irq(int irq, void *dev_id)
     49 {
     50     struct pin_desc * pindesc = (struct pin_desc *)dev_id;
     51     unsigned int pinval;
     52     
     53     pinval = s3c2410_gpio_getpin(pindesc->pin);
     54 
     55     if (pinval)
     56     {
     57         /* 松开 */
     58         key_val = 0x80 | pindesc->key_val;
     59     }
     60     else
     61     {
     62         /* 按下 */
     63         key_val = pindesc->key_val;
     64     }
     65 
     66     ev_press = 1;                  /* 表示中断发生了 */
     67     wake_up_interruptible(&key_waitq);   /* 唤醒休眠的进程 */
     68     return IRQ_RETVAL(IRQ_HANDLED);
     69 }
     70 
     71 static int key_drv2_open(struct inode *inode, struct file *file)
     72 {
     73     /* 配置GPF0,2为输入引脚 */
     74     /* 配置GPG3,11为输入引脚 */
     75     request_irq(IRQ_EINT0,  keys_irq, IRQT_BOTHEDGE, "S2", &pins_desc[0]);
     76     request_irq(IRQ_EINT2,  keys_irq, IRQT_BOTHEDGE, "S3", &pins_desc[1]);
     77     request_irq(IRQ_EINT11, keys_irq, IRQT_BOTHEDGE, "S4", &pins_desc[2]);
     78     request_irq(IRQ_EINT19, keys_irq, IRQT_BOTHEDGE, "S5", &pins_desc[3]);    
     79 
     80     return 0;
     81 }
     82 
     83 ssize_t key_drv2_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
     84 {
     85     if (size != 1)
     86         return -EINVAL;
     87 
     88     /* 如果没有按键动作, 休眠 */
     89     wait_event_interruptible(key_waitq, ev_press);
     90 
     91     /* 如果有按键动作, 返回键值 */
     92     copy_to_user(buf, &key_val, 1);
     93     ev_press = 0;
     94     return 1;
     95 }
     96 
     97 int key_drv2_close(struct inode *inode, struct file *file)
     98 {
     99     free_irq(IRQ_EINT0, &pins_desc[0]);
    100     free_irq(IRQ_EINT2, &pins_desc[1]);
    101     free_irq(IRQ_EINT11, &pins_desc[2]);
    102     free_irq(IRQ_EINT19, &pins_desc[3]);
    103     return 0;
    104 }
    105 
    106 
    107 static struct file_operations sencod_drv_fops = {
    108     .owner   =  THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    109     .open    =  key_drv2_open,     
    110     .read     =    key_drv2_read,       
    111     .release =  key_drv2_close,       
    112 };
    113 
    114 int major;
    115 static int key_drv_init(void)
    116 {
    117     major = register_chrdev(0, DEVICE_NAME, &sencod_drv_fops);
    118 
    119     key_class = class_create(THIS_MODULE, DEVICE_NAME);
    120 
    121     key_class_dev = class_device_create(key_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME); /* /dev/keys */
    122 
    123     gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
    124     gpfdat = gpfcon + 1;
    125 
    126     gpgcon = (volatile unsigned long *)ioremap(0x56000060, 16);
    127     gpgdat = gpgcon + 1;
    128 
    129     return 0;
    130 }
    131 
    132 static void key_drv_exit(void)
    133 {
    134     unregister_chrdev(major, DEVICE_NAME);
    135     class_device_unregister(key_class_dev);
    136     class_destroy(key_class);
    137     iounmap(gpfcon);
    138     iounmap(gpgcon);
    139     return 0;
    140 }
    141 
    142 module_init(key_drv_init);
    143 
    144 module_exit(key_drv_exit);
    145 
    146 MODULE_LICENSE("GPL");
    View Code

    驱动代码

     1 #include <sys/types.h>
     2 #include <sys/stat.h>
     3 #include <fcntl.h>
     4 #include <stdio.h>
     5 
     6 /* thirddrvtest 
     7   */
     8 int main(int argc, char **argv)
     9 {
    10     int fd;
    11     unsigned char key_val;
    12     
    13     fd = open("/dev/key_dev2", O_RDWR);
    14     if (fd < 0)
    15     {
    16         printf("can't open!
    ");
    17     }
    18 
    19     while (1)
    20     {
    21         read(fd, &key_val, 1);
    22         printf("key_val = 0x%x
    ", key_val);
    23     }
    24     
    25     return 0;
    26 }
    View Code

     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 obj-m    += key_dev2.o
    View Code
  • 相关阅读:
    Vue 2.x windows环境下安装
    VSCODE官网下载缓慢或下载失败 解决办法
    angular cli 降级
    Win10 VS2019 设置 以管理员身份运行
    XSHELL 连接 阿里云ECS实例
    Chrome浏览器跨域设置
    DBeaver 执行 mysql 多条语句报错
    DBeaver 连接MySql 8.0 报错 Public Key Retrieval is not allowed
    DBeaver 连接MySql 8.0报错 Unable to load authentication plugin 'caching_sha2_password'
    Linux系统分区
  • 原文地址:https://www.cnblogs.com/yang-cheng/p/13429892.html
Copyright © 2011-2022 走看看