arm驅動程序——按鍵程序1(韋東山的視頻總結及針對linux-2.6.30)

相關代碼在資源中下載。

按鍵程序是以中斷方式寫的,至於中斷的內核相關的知識看中斷框架和註冊一節,

所用到的函數和結構:

/*用來註冊中斷*/

/*irq:中斷號,handler:中斷處理函數,flags:中斷觸發方式,

 *name:中斷名字,dev:用來傳給中斷函數的*/

static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, 

            unsigned long flags,const char *name, void *dev)


/*用來釋放住的request_irq*/
void free_irq(unsigned int irq, void *dev_id);

驅動程序:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/device.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <mach/irqs.h>
/*不同的linux版本的頭文件會有所不同*/
static int major;
static struct class  *second_key_class;
static struct device *second_key_device;
volatile unsigned long *GPFCON = NULL;
volatile unsigned long *GPFDAT = NULL;
static irqreturn_t buttons_irq(int irq,void *dev_id){

      printk("irq= %d \n",irq);
      return IRQ_HANDLED;
}
static int second_key_open(struct inode *inode, struct file *file)
{
     /*設置相應引腳設置成中斷方式*/
      *GPFCON &= ~((3<<0)|(3<<2)|(3<<4)|(3<<8));
      *GPFCON |= (1<<1)|(1<<3)|(1<<5)|(1<<7);
     /*中斷註冊*/
      request_irq(IRQ_EINT1,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s1",1);
      request_irq(IRQ_EINT4,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s2",1);
      request_irq(IRQ_EINT2,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s3",1);
      request_irq(IRQ_EINT0,buttons_irq,IRQ_TYPE_EDGE_BOTH,"s4",1);
      return 0;
}
static ssize_t second_key_read(struct file *file, char __user *user_buffer, 

                               size_t count, loff_t *ppos)
{
     unsigned long reval;
     int i;
     unsigned long key_val[4];
     /*讀出引腳狀態*/
     reval = *GPFDAT;
     if(count != sizeof(key_val))
         return -EINVAL;
     key_val[0] = (reval & (0x01<<0)) ? 1 : 0;
     key_val[1] = (reval & (0x01<<1)) ? 1 : 0;
     key_val[2] = (reval & (0x01<<2)) ? 1 : 0;
     key_val[3] = (reval & (0x01<<4)) ? 1 : 0;
     /*把內核的數據傳到用戶空間*/
     copy_to_user(user_buffer,key_val,4);
     return 4;
}
static int second_key_close(struct inode *inode, struct file *file)
{
     /*釋放分配的request_irq*/
     free_irq(IRQ_EINT1,1);
     free_irq(IRQ_EINT4,1);
     free_irq(IRQ_EINT2,1);
     free_irq(IRQ_EINT0,1);
     return 0;
}
/*定義一個file_operations結構*/
static struct file_operations second_key_fops =
{
    .owner   = THIS_MODULE,
    .open    = second_key_open,
    .read    = second_key_read,
    .release = second_key_close,
};
/*入口函數*/
static int  second_key_init(void)
{
    /*註冊*/
    major =register_chrdev(0,"second_key1",&second_key_fops);
    /*分配一個類*/
    second_key_class = class_create(THIS_MODULE,"second_key_class");
    /*類下面創建一個設備*/
    second_key_device = 
    device_create(second_key_class,NULL,MKDEV(major,0),NULL,"buttons");
    /*映射物理地址到虛擬地址*/
    GPFCON = (volatile unsigned long *)ioremap(0x56000050,16);
    GPFDAT = GPFCON + 1;
    return 0;
}
/*出口函數*/
static void second_key_exit(void)
{
    /*註銷*/
    unregister_chrdev(major,"second_key1");
    /*從系統中註銷設備*/
    device_unregister(second_key_device);
    /*銷燬創建的類*/
    class_destroy(second_key_class);

    /*取消虛擬地址的映射*/
    iounmap(GPFCON);
}
/*修飾*/
module_init(second_key_init);
module_exit(second_key_exit);
MODULE_LICENSE("GPL");

下面測試:

1,加載到內核 insmod second_key1.ko

2,打開中斷設備 exec 5</dev/buttons

3, 按下按鍵 終端出現中斷號

4,關閉中斷設備 exec 5<&-

exec 5</dev/buttons 是用shell打開文件

你可以用ps查看/bin/sh的進程號,然後用ls -l /proc/進程號/fd

可以看到lr -x    1 root     root            64 Apr 29 17:04 5 -> /dev/buttons



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章