下面为我自己写的ST2410按键驱动源码。按键使用外部中断EINT19,Linux系统中断号为63。写的有点粗糙。还需理解和加深Linux内核中断机制。再完成更完善的程序。
/*2008-06-27*/
/*熊焱春*/
#include <linux/kernel.h>//内核头文件
#include <linux/module.h>//模块加载的头文件
#include <linux/init.h>//Need for the macros:module_init and module_exit
#include <linux/config.h>//配置头文件
#include <asm/hardware.h>
#include <linux/fs.h>
#include <linux/interrupt.h>//irq_request
#include <linux/timer.h>
#include <asm-arm/arch-s3c2410/regs-gpio.h> //S3C2410_GPGCON
#include <asm-arm/arch-s3c2410/regs-irq.h> //S3C2410_EINTMSK
#include <asm/io.h> //for __raw_writel函数
//#include <asm-arm/arch-s3c2410/hardware.h> //s3c2410_gpio_cfgpin函数
MODULE_******("Dual BSD/GPL");//module.h
MODULE_AUTHOR("Xiong Yanchun");
MODULE_DESCRIPTION("keydriver");
//#define DEVICE_NAME "key"//设备名
int keydriver_major=200;//主设备号
#define key_irq 63 //中断号
static int key_temp_count=0;
/********************OPEN********************/
static int key_open(struct inode *inode,struct file *file)
{
printk("\nIt's in key_open function---in the keydriver.ko!!!\n");
//MOD_INC_USE_COUNT;
return 0;
}
/********************READ********************/
static ssize_t key_read(struct file *filp,char __user *buf,size_t count,loff_t *fops)
{
printk("\nIt's in key_read function---in the keydriver.ko!!!\n");
return count;
}
/********************WRITE********************/
static ssize_t key_write(struct file *filp,const char __user *buf,size_t count,loff_t *fops)
{
printk("\nIt's in key_write function---in the keydriver.ko!!!\n");
return count;
}
/********************IOCTL********************/
static int key_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long date)
{
printk("\nIt's in key_ioctl function---in the keydriver.ko!!!\n");
return 0;
}
/********************RELEASE********************/
static int key_release(struct inode *inode,struct file *file)
{
printk("\nIt's in key_release function---in the keydriver.ko!!!\n");
return 0;
}
struct file_operations keydriver_fops=
{
//.owner=THIS_MODULE,
.open=key_open,
.read=key_read,
.write=key_write,
.ioctl=key_ioctl,
.release=key_release,
};
/*中断处理函数*/
static void key_interrupt(int irq,void *dev_id,struct pt_regs *regs)
{
key_temp_count++;
printk("Now key interrupt occur %d times!!!\n",key_temp_count);
}
static int __init keydriver_init(void)
{
printk("\nHello,it's a keydriver---in the keydriver.ko!!!\n");
unsigned int ret = -ENODEV;
//注册设备:主设备号,设备名,文件操作结构体地址
ret = register_chrdev(keydriver_major,"key",&keydriver_fops);
if(ret<0)
{
printk("init_module failed with %d---in the keydriver.ko\n",ret);
return ret;
}
else
{
printk("init_module keydriver success---in the keydriver.ko!!!\n");
}
//__raw_writel(0x00800000,S3C2410_GPGCON);//EINT19,这种方法不太好,改变了其他位.
printk("S3C2410_GPGCON=%x\n",readl(S3C2410_GPGCON));
//writel((readl(S3C2410_GPGCON)|0x00800000)&~(1<<23),S3C2410_GPGCON);
writel((readl(S3C2410_GPGCON)|(1<<23))&(~(1<<22)),S3C2410_GPGCON);
//s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_EINT19);
printk("S3C2410_GPGCON=%x\n",readl(S3C2410_GPGCON));
writel(readl(S3C2410_INTMSK)&(~(1<<6)),S3C2410_INTMSK);//INTMASK寄存器
//中断请求:注册中断号,注册中断处理函数,标志,设备名设备标识
ret=request_irq(key_irq,&key_interrupt,SA_INTERRUPT,"key",NULL);
//初始化硬件部分搞一个按键的试试
printk("\n...............\nret=%d\n.........\n",ret);
return ret;
}
//初始化按键
static int __init S3C2410_keydriver_init(void)
{
int ret = -ENODEV;
ret = keydriver_init();
if(ret)
return ret;
return 0;
}
static void __exit keydriver_exit(void)
{//注销设备并释放中断
unregister_chrdev(keydriver_major,"key");//主设备号,设备名
printk("unregister keydriver success!!!\n");
free_irq(key_irq,NULL);//interrupt.h
printk("free irq %d success!!!\n",key_irq);
}
module_init(S3C2410_keydriver_init);
module_exit(keydriver_exit);
按键为异步事件,不需要测试代码。