【FAQ】全志R系列如何解决gpio-keys驱动在系统启动上报两次input事件?
-
问题背景
硬件:R系列板子
软件:Tina3.5问题简述
在Tina全部版本中,选用gpio-keys驱动,在系统上电时从log信息发现gpio-keys驱动自动上报了两次按键弹起的input事件。
问题分析
上报两次input事件的原因一共有两个,分别如下所示:
1.由中断状态机误报一次中断。在gpio-keys驱动在初始化时,设置了软件上拉GPIO(或者是在硬件中上拉),对于中断状态机来说,外部GPIO已经是属于高电平了。在request_irq时,中断检测电路开始初始化,当前中断状态机的移位寄存器为0000(PS:中断检测电路用4bit来表示当前的中断触发方式,比如说0000认为外部是低电平,触发低电平中断)。
当GPIO的功能寄存器设置为中断功能,中断状态机开始移位检测。因为当前GPIO为高电平,两个CLK时钟周期后,中断状态机的移位寄存器会出现0011的情况,这时候,即使未出现上升沿,也会认为触发了一次上升沿中断。
这是中断误报属于硬件寄存器的问题,无法取消,只能规避。不过这个只会误报一次,后续驱动正常工作下不会再次误报的。除非设置改GPIO的复用功能为非中断功能,然后再设置GPIO为中断功能,这时候中断状态机又会重新初始化和误报一次中断。
解决方法:
- 在配置GPIO复用功能之后,等待一段时间,清一遍pending,去除第一次误触发中断。另外,在使用过程中,不要动态切换GPIO的复用功能。
- 在gpio-keys驱动中,定义一些变量,强行让中断处理函数不去处理第一次中断事件。
2.由gpio-keys的gpio_keys_open()函数上报的:
static int gpio_keys_open(struct input_dev *input) { struct gpio_keys_drvdata *ddata = input_get_drvdata(input); const struct gpio_keys_platform_data *pdata = ddata->pdata; int error; if (pdata->enable) { error = pdata->enable(input->dev.parent); if (error) return error; } /* Report current state of buttons that are connected to GPIOs */ gpio_keys_report_state(ddata); return 0; }
gpio_keys_open()函数最终调用gpio_keys_report_state()函数来上报按键当前状态。在驱动probe函数和resume函数都会运行该函数。
这个函数是否需要运行主要取决于应用层的工作逻辑,不想在probe或者resume上报当前按键状态的话,也可以在代码中注释掉该函数。
-
-
-
-
-
Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号