记一次gpio唤醒调试

使用TP的IRQ脚做手势唤醒。双击屏幕后,从log看cpu已经被唤醒了,但很快又睡下去,通过log分析,发现没有进入中断处理函数。这里使用的电平中断。以前已分析过电平/边沿唤醒cpu流程https://blog.csdn.net/mike8825/article/details/98473014,打印发现handle_level_irq只跑了一遍,第二次的handle_level_irq没有过来导致无法进入中断函数。一开始怀疑是低电平的持续时间不够,导致没有第二次中断过来。修改TP的固件,让TP的IRQ拉低到500ms,也是一样的情况,也用示波器确认信号确实拉低了500ms。跟cpu厂商那边沟通,说该cpu支持边沿唤醒,也支持电平唤醒,建议用边沿唤醒测试。修过代码后,边沿唤醒的确有效,但电平唤醒为什么不会进入中断。fae加了一些打印信息,也发现什么异常。

查看cpu手册,gpio支持dbc和level模式,再看下gpio代码,只有dbc模式才会设置电平模式,所以设置电平中断没有成功,导致还是边沿的电平触发方式,所以中断只会过来一次,第二次中断没有过来,导致没有进入中断模式,也就是平台代码的BUG。

static int sprd_gpio_plus_irq_set_type(struct irq_data *data,unsigned int flow_type)
{
    case IRQ_TYPE_LEVEL_LOW:
		mode = sprd_gpio_plus_read(chip, channel, REG_INT_CRL,
			BIT_INT_MODE, INT_MODE_WIDTH);
		dbnc = sprd_gpio_plus_read(chip, channel, REG_INT_CRL,
			BIT_DBC_CYCLE, DBC_CYCLE_WIDTH);
		if ((mode == GPIO_INT_DBC_MODE) && (dbnc == 0)) {
			sprd_gpio_plus_write(chip, channel, REG_INT_CRL,
			BIT_INT_MODE, INT_MODE_WIDTH, GPIO_INT_LEVEL_MODE);
		}
		sprd_gpio_plus_write(chip, channel, REG_INT_CRL,
			BIT_INT_LEVEL, 1, 0);
		irq_set_handler_locked(data, handle_level_irq);
		break;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章