提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
记录一下GPIO 中断demo,需要用的时候直接赋值修改即可。如果中断后判断高低电平,可以通过定时器加入一个防抖动的机制。
demo
/*
* int gpio_iddig_irq; 是g_extcon结构体里的私有数据
*/
//g_extcon是全局 私有数据
int request_irq_func(struct device *dev)
{
//申请中断
g_extcon->gpio_iddig_irq = of_get_named_gpio(dev->of_node, "gpio-iddig-irq", 0);
ret = devm_gpio_request(dev, g_extcon->gpio_iddig_irq, "gpio-iddig-irq");
if (ret) {
printk("%s request gpio %d failed: %d\n", __func__, g_extcon->gpio_iddig_irq, ret);
} else {
printk("%s 11 request gpio %d failed: %d\n", __func__, g_extcon->gpio_iddig_irq, ret);
gpio_direction_input(g_extcon->gpio_iddig_irq);
}
ret = gpio_to_irq(g_extcon->gpio_iddig_irq);
if (ret < 0) {
gpio_free(g_extcon->gpio_iddig_irq);
printk("%s gpio_to_irq gpio %d failed: %d\n", __func__, g_extcon->gpio_iddig_irq, ret);
}
ret = request_irq(ret, gpio_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "gpio-iddig-irq", NULL);
if (ret) {
gpio_free(g_extcon->gpio_iddig_irq);
printk("%s request_irq gpio %d failed: %d\n", __func__, g_extcon->gpio_iddig_irq, ret);
}
//定时器初始化
timer_init_func();
return 0;
}
//中断处理函数
static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
{
/* 在这里编写中断发生时需要执行的代码 */
printk("%s GPIO interrupt detected++!\n", __func__);
//关闭中断,防止中断嵌套
disable_irq_nosync(g_extcon->gpio_iddig_irq);
//定时器处理,这个定时器是消抖()
//这段内容懒得删除了,但是中断里面不建议使用定时器,容易出现内核崩溃的情况
//具体为:bad: scheduling from the idle thread!
//这里建议使用延时的工作队列去处理(线程也可以)
mod_timer(&g_extcon->usb_ed_timer, HZ / 10); //100ms消抖
printk("%s GPIO interrupt detected--!\n", __func__);
return IRQ_HANDLED;
}
//定时器初始化
int timer_init_func()
{
/*
* struct timer_list usb_ed_timer;是全局g_extcon里的属性
*/
timer_setup(&g_extcon->usb_ed_timer, usb_ed_worker, 0);
g_extcon->usb_ed_timer.expires = jiffies + HZ/10; //100ms定时
add_timer(&g_extcon->usb_ed_timer);
return 0;
}
//定时器工作函数
static void usb_ed_worker(struct timer_list* timer_l)
{
int value;
printk("%s ++ \n", __func__);
value = gpio_get_value(g_extcon->gpio_iddig_irq);
if(value == 0) {
//接入U盘等设备
printk("%s plug in perih device \n", __func__);
} else {
//拔出U盘
printk("%s plug out perih device \n", __func__);
}
printk("%s -- \n", __func__);
//重新使能中断
enable_irq(g_extcon->gpio_iddig_irq);
}