和字符驱动程序一样,先学习驱动框架,再研究构成框架的这些注册函数在内核是怎么工作的。
mini2440的6个按键连接在gpg0,3,5,6,7,11上,中断号是8,11,13,14,15,19共用一个中断eint8-23,在irqs.h中有所有中断号的宏定义。在interrupt.h中有中断触发方式的宏定义。
int devid=1;
static struct class *seconddrv_class;
static struct device *seconddrv_class_dev;
volatile unsigned long *gpgcon;
volatile unsigned long *gpgdat;//mini2440的6个按键连接在gpg0,3,5,6,7,11上
static irqreturn_t botton_handle(int irq, void *dev_id)//
irq为linux提供的中断号,dev_id可以看做该中断下不同中断函数的id,irqreturn_t的宏定义在
{
//irqreturn.h中,是一个枚举
printk("irq=%d\n",irq);
return IRQ_HANDLED;
}//注册的中断响应函数
static int second_drv_close(struct inode *inode, struct file *file)
{
free_irq(IRQ_EINT8,&devid);
free_irq(IRQ_EINT11,&devid);
free_irq(IRQ_EINT13,&devid);
free_irq(IRQ_EINT14,&devid);
free_irq(IRQ_EINT15,&devid);
free_irq(IRQ_EINT19,&devid);
return 0;
}//解除注册
static int second_drv_open(struct inode *inode, struct file *file)
{
*gpgcon &= ~((3<<0)|(3<<6)|(3<<10)|(3<<12)|(3<<14)|(3<<22));
*gpgcon |= (2<<0)|(2<<6)|(2<<10)|(2<<12)|(2<<14)|(2<<22);//中断配置
request_irq(IRQ_EINT8,botton_handle,IRQF_TRIGGER_RISING,"bottontest1",&devid);
request_irq(IRQ_EINT11,botton_handle,IRQF_TRIGGER_RISING,"bottontest2",&devid);
request_irq(IRQ_EINT13,botton_handle,IRQF_TRIGGER_RISING,"bottontest3",&devid);
request_irq(IRQ_EINT14,botton_handle,IRQF_TRIGGER_RISING,"bottontest4",&devid);
request_irq(IRQ_EINT15,botton_handle,IRQF_TRIGGER_RISING,"bottontest5",&devid);
request_irq(IRQ_EINT19,botton_handle,IRQF_TRIGGER_RISING,"bottontest6",&devid);
return 0;
}//注册六个按键的中断函数并自动完成打开中断需要的所有工作
static struct file_operations sencod_drv_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = second_drv_open,
.release = second_drv_close,
};
int major;
static int second_drv_init(void)
{
major = register_chrdev(0, "botton_drv", &sencod_drv_fops);
seconddrv_class = class_create(THIS_MODULE, "second_drv");
seconddrv_class_dev = device_create(seconddrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */
gpgcon = (volatile unsigned long *)ioremap(0x56000060, 16);
gpgdat = gpgcon + 1;
return 0;
}
static void second_drv_exit(void)
{
unregister_chrdev(major, "second_drv");
device_destroy(seconddrv_class,MKDEV(major, 0));
class_destroy(seconddrv_class);
iounmap(gpgcon);
}
module_init(second_drv_init);
module_exit(second_drv_exit);
MODULE_LICENSE("GPL");
最后在板子上测试发现6个按键有5个已经被内核注册为键盘了,需要在内核配置中取消device/drive/input device support/keyboard再重新编译内核,执行exec 5 关于exec的用法看:http://blog.chinaunix.net/uid-26798528-id-3497940.html
linux exec用法总结