新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 嵌入式Linux设备驱动开发之:按键驱动程序实例

嵌入式Linux设备驱动开发之:按键驱动程序实例

作者:时间:2013-09-13来源:网络收藏

本文引用地址:http://www.amcfsurvey.com/article/257107.htm

按键字符设备的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*/

if((ucKey>=1)(ucKey=16))

{

/*如果缓冲区已满,则不添加*/

if(((key_buffer.head+1)(MAX_KEY_COUNT-1))!=key_buffer.tail)

{

spin_lock_irq(buffer_lock);

key_buffer.buf[key_buffer.tail]=ucKey;

key_buffer.jiffy[key_buffer.tail]=get_tick_count();

key_buffer.tail++;

key_buffer.tail=(MAX_KEY_COUNT-1);

spin_unlock_irq(buffer_lock);

}

}

init_gpio();/*初始化GPIO端口,主要是为了恢复中断端口配置*/

enable_irqs();/*开启中断*/

returnIRQ_HANDLED;/*2.6内核返回值一般是这个宏*/

}

/*申请4个中断*/

staticintrequest_irqs(void)

{

intret,i,j;

for(i=0;iMAX_COLUMN;i++)

{

ret=request_irq(key_info_matrix[i][0].irq_no,

button_irq,SA_INTERRUPT,BUTTONS_DEVICE_NAME,NULL);

if(ret0)

{

for(j=0;ji;j++)

{

free_irq(key_info_matrix[j][0].irq_no,NULL);

}

return-EFAULT;

}

}

return0;

}

/*释放中断*/

static__inlinevoidfree_irqs(void)

{

inti;

for(i=0;iMAX_COLUMN;i++)

{

free_irq(key_info_matrix[i][0].irq_no,NULL);

}

}

中断处理函数在每次中断产生的时候会被调用,因此它的执行时间要尽可能得短。通常中断处理函数只是简单地唤醒等待资源的任务,而复杂且耗时的工作则让这个任务去完成。中断处理函数不能向用户空间发送数据或者接收数据,不能做任何可能发生睡眠的操作,而且不能调用schedule()函数。

为了简单起见,而且考虑到按键操作的时间比较长,在本实例中的中断处理函数button_irq()里,通过调用睡眠函数来消除毛刺信号。读者可以根据以上介绍的对中断处理函数的要求改进该部分代码。

linux操作系统文章专题:linux操作系统详解(linux不再难懂)

linux相关文章:linux教程


蜂鸣器相关文章:蜂鸣器原理


评论


相关推荐

技术专区

关闭