设为首页 加入收藏

TOP

AT9260 GPIO中断(二)
2014-11-24 14:37:03 来源: 作者: 【 】 浏览:5
Tags:AT9260 GPIO 中断
iffies + KEY_TIMER_DELAY1;// 延迟
add_timer(&key_timer[key]); // 启动定时器



return IRQ_HANDLED; //正确的中断
}
// 定时器处理函数
static void key_timer_handler(unsigned long data)
{
int key = data;
//获取当前按键引脚上的电平值来判断按键是按下还是抬起
int up = at91_get_gpio_value(key_info_tab[key].gpio_port);
if (!up)
{
if (key_dev.keyStatus[key] == KEYSTATUS_DOWNX)
//从中断进入
{
key_dev.keyStatus[key] = KEYSTATUS_DOWN;
key_timer[key].expires = jiffies + KEY_TIMER_DELAY2; //延迟
keyEvent(key); //记录键值,唤醒等待队列
add_timer(&key_timer[key]);
}
else
{
key_timer[key].expires = jiffies + KEY_TIMER_DELAY2; //延迟
add_timer(&key_timer[key]);
}
}
else //键已抬起
{
key_dev.keyStatus[key] = KEYSTATUS_UP;
enable_irq(key_info_tab[key].irq_no);
}
}




// 按键设备驱动的中断申请函数
// 申请系统中断,中断方式为下降沿触发
static int request_irqs(void)
{
struct key_info *k;
int i;
int ret;
for(i = 0; i < sizeof(key_info_tab)/sizeof(key_info_tab[1]); i++)
// for(i = 0; i < 1; i++)
{
k = key_info_tab + i;
//设置4个IO口为中断下降沿触发方式
set_irq_type(key_info_tab[i].irq_no, key_info_tab[i].irq_type); // 设置中断类型

//申请中断(类型为快速中断,中断服务时屏蔽所有外部中断?)将按键序列号作为参数传入中断服务程序
// if(request_irq(k->irq_no,at91sam9260_enit_key,0,DEVICE_NAME,(void *)i))
ret = request_irq(k->irq_no,at91sam9260_enit_key,0,DEVICE_NAME,(void *)i);
if(ret)
{
printk(KERN_NOTICE "buttons:ret is %d\r\n",ret);
return -1;
}
}



return 0;

}
// 释放中断
static void free_irqs(void)
{
struct key_info *k;
int i;



for(i = 0; i < sizeof(key_info_tab)/sizeof(key_info_tab[1]); i++)
{
k = key_info_tab + i;
free_irq(k->irq_no,(void *)i);
}

}






// 按键设备驱动的打开、释放函数
static int at91sam9260_key_open(struct inode *inode, struct file *filp)
{
key_dev.head = key_dev.tail = 0; //清空按键动作缓冲区
// keyEvent = keyEvent_raw; //函数指针指向按键处理函数keyEvent_raw

return 0;
}



static int at91sam9260_key_release(struct inode *inode, struct file *filp)
{
// keyEvent = keyEvent_dummy; //函数指针指向空函数

return 0;
}




// 按键设备驱动读函数
static ssize_t at91sam9260_key_read(struct file *filp, char __user *buf, ssize_t count,
loff_t*ppos)
{
unsigned int key_ret;
unsigned long flags;
retry:
if (key_dev.head != key_dev.tail) // 缓冲区有数据?
{
local_irq_save(flags); // 进入临界区 ,关中断
key_ret = BUF_TAIL; // 读出键值
key_dev.tail = INCBUF(key_dev.tail, MAX_KEY_BUF); // 调整缓冲区尾指针
local_irq_restore(flags); // 退出临界区,开中断
if(copy_to_user(buf, (void *)&key_ret, sizeof(unsigned int))) // 拷贝到用户空间
{
return -EFAULT;
}
else
{
return sizeof(unsigned int);
}

}
else // 缓冲区没数据
{
if (filp->f_flags & O_NONBLOCK) // 若采用非阻塞方式读取则返回错误
{
return -EAGAIN;
}
interruptible_sleep_on(&(key_dev.wq)); // 使进程睡眠
if (signal_pending(current)) //在这里等中断
{ // 如果是信号中断
return -ERESTARTSYS;
}
goto retry;
}

return sizeof(unsigned int);

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇AT91SAM9261的LINUX2.6 GPIO与GPI.. 下一篇Android Matrix图片随意的放大缩..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: