嵌入式Linux设备驱动开发之:按键驱动程序实例
c2410_gpio_cfgpin(S3C2410_GPE11,S3C2410_GPE11_OUTP);/*GPE11*/
s3c2410_gpio_setpin(S3C2410_GPE11,0);
s3c2410_gpio_cfgpin(S3C2410_GPE13,S3C2410_GPE13_OUTP);/*GPE13*/
s3c2410_gpio_setpin(S3C2410_GPE13,0);
s3c2410_gpio_cfgpin(S3C2410_GPG2,S3C2410_GPG2_OUTP);/*GPG2*/
s3c2410_gpio_setpin(S3C2410_GPG2,0);
s3c2410_gpio_cfgpin(S3C2410_GPG6,S3C2410_GPG6_OUTP);/*GPG6*/
s3c2410_gpio_setpin(S3C2410_GPG6,0);
s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0);/*GPF0*/
s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2);/*GPF2*/
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_EINT11);/*GPG3*/
s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_EINT19);/*GPG11*/
set_irq_type(IRQ_EINT0,IRQT_FALLING);
set_irq_type(IRQ_EINT2,IRQT_FALLING);
set_irq_type(IRQ_EINT11,IRQT_FALLING);
set_irq_type(IRQ_EINT19,IRQT_FALLING);
}
下面讲解按键驱动的主要接口,以下为驱动模块的入口和卸载函数。
/*初始化并添加structcdev结构到系统之中*/
staticvoidbutton_setup_cdev(structcdev*dev,
intminor,structfile_operations*fops)
{
interr;
intdevno=MKDEV(button_major,minor);
cdev_init(dev,fops);/*初始化结构体structcdev*/
dev->owner=THIS_MODULE;
dev->ops=fops;/*关联到设备的file_operations结构*/
err=cdev_add(dev,devno,1);/*将structcdev结构添加到系统之中*/
if(err)
{
printk(KERN_INFOError%daddingbutton%d\n,err,minor);
}
}
……
/*驱动初始化*/
staticintbutton_init(void)
{
intret;
/*将主设备号和次设备号定义到一个dev_t数据类型的结构体之中*/
dev_tdev=MKDEV(button_major,0);
if(button_major)
{/*静态注册一个设备,设备号先前指定好,并设定设备名,用cat/proc/devices来查看*/
ret=register_chrdev_region(dev,1,BUTTONS_DEVICE_NAME);
}
else
{/*由系统动态分配主设备号*/
ret=alloc_chrdev_region(dev,0,1,BUTTONS_DEVICE_NAME);
button_major=MAJOR(dev);/*获得主设备号*/
}
if(ret0)
{
printk(KERN_WARNINGButton:unabletogetmajor%d\n,button_major);
returnret;
}
/*初始化和添加结构体structcdev到系统之中*/
button_setup_cdev(button_dev,0,button_fops);
printk(Buttondriverinitialized.\n);
return0;
}
/*驱动卸载*/
staticvoid__exitbutton_exit(void)
{
cdev_del(button_dev);/*删除结构体structcdev*/
/*卸载设备驱动所占有的资源*/
unregister_chrdev_region(MKDEV(button_major,0),1);
printk(Buttondriveruninstalled\n);
}
module_init(button_init);/*初始化设备驱动程序的入口*/
module_exit(button_exit);/*卸载设备驱动程序的入口*/
MODULE_AUTHOR(David);
MODULE_LICENSE(DualBSD/GPL);
按键字符设备的file_operations结构定义为:
staticstructfile_operationsbutton_fops=
{
.owner=THIS_MODULE,
.ioctl=button_ioctl,
.open=button_open,
.read=button_read,
.release=button_release,
};
以下为open和release函数接口的实现。
/*打开文件,申请中断*/
staticintbutton_open(structinode*inode,structfile*filp)
{
intret=nonseekable_open(inode,filp);
if(ret0)
{
returnret;
}
init_gpio();/*相关GPIO端口的初始化*/
ret=request_irqs();/*申请4个中断*/
if(ret0)
{
returnret;
}
init_keybuffer();/*初始化按键缓冲数据结构*/
returnret;
}
/*关闭文件,屏蔽中断*/
staticintbutton_release(structinode*inode,structfile*filp)
{
free_irqs();/*屏蔽中断*/
return0;
}
在open函数接口中,进行了GPIO端口的初始化、申请硬件中断以及按键缓冲的初始化等工作。在以前的章节中提过,中断端口是比较宝贵而且数量有限的资源。因此需要注意,最好要在第一次打开设备时申请(调用request_irq函数)中断端口,而不是在驱动模块加载的时候申请。如果已加载的设备驱动占用而在一定时间段内不使用某些中断资源,则这些资源不会被其他驱动所使用,只能白白浪费掉。而在打开设备的时候(调用open函数接口)申请中断,则不同的设备驱动可以共享这些宝贵的中断资源。
以下为中断申请和释放的部分以及中断处理函数。
/*中断处理函数,其中irq为中断号*/
staticirqreturn_tbutton_irq(intirq,void*dev_id,structpt_regs*regs)
{
unsignedcharucKey=0;
disable_irqs();/*屏蔽中断*/
/*延迟50ms,屏蔽按键毛刺*/
udelay(50000);
ucKey=button_scan(irq);/*扫描按键,获得进行操作的按键的ID*/
i
嵌入式Linux 设备驱动 按键驱动程序 操作系统 相关文章:
- 嵌入式Linux技术在工业控制网络中的应用(10-30)
- 基于嵌入式Linux的组态软件实时数据库的设计(02-01)
- 基于ARM+DSP的嵌入式Linux数控系统设计(11-18)
- 基于嵌入式Linux的细胞特征提取算法设计(11-19)
- 基于S3C2410的嵌入式Linux系统构建(03-02)
- 嵌入式Linux网络编程之:网络基础编程(08-13)