RV1106 编写基于input 子系统的按键驱动程序遇到的问题总结

一、背景描述

1. 处理器与Linux 版本

  • ROCKCHIP RV1106
  • Linux 5.10.110

2. 按键对应的IO口

gpio1_pd1

3. 检测算法

按键按下

按键被按下时,按键IO 产生下降沿中断,在中断处理函数中,开启定时器进行防抖处理,防抖时间结束,按键还是保持低电平状态,则用input 子系统的上报按键按下事件。

按键弹起

按键弹起时,按键IO 产生上升沿中断,在中断处理函数中,开启定时器进行防抖处理,防抖时间结束,按键还是保持高电平状态,则用input 子系统的上报按键弹起事件。

二、修改设备树

1. 添加 pinctrl 子节点

&pinctrl{
          gpio1-pd1 {
                gpio1_pd1:gpio1-pd1{
                        rockchip,pins = <1 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
};

2. 添加gpio 子节点

gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_LOW>;

3.中断相关的设备树属性

interrupts-parent = <&gpio1>;
interrupts = <RK_PD1 IRQ_TYPE_EDGE_BOTH>;

4. 按键对应的IO 节点的定义如下

gpio1pd1:gpio1pd1{
        compatible = "gpio1_pd1";
        pinctrl-names = "default";                                                                                                                                                                             pinctrl-0 = <&gpio1_pd1>;
        regulator-name ="gpio1_pd1";
        gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>;
        interrupts-parent = <&gpio1>;                                                                                                                                                                          interrupts = <RK_PD1 IRQ_TYPE_EDGE_FALLING>;
        regulator-always-on;
};     

三、遇到的问题

1. 按键按下时,能响应中断处理函数,但是开启定时器进行防抖时,定时器超时中断没执行

在中断处理函数中,调用 mod_timer 函数修改超时时间并开启定时器时,第二个参数理解出错,当时是这样写的:

mod_timer( &g_key.timer,  20  );

mcu 程序时,软件定时器的超时时间一般是ms 为单位,现在切换到Linux 驱动程序,没切换过来,还想着填入一个20 ms 作为超时时间。

实际上,mod_timer 函数的第二个参数描述的是在系统节拍为 expires 时,调用超时处理函数。所以,应该改成下面所示:

mod_timer( &g_key.timer, jiffies + msecs_to_jiffies( 20 ) );

2. 驱动层在防抖结束之后,使用input 子系统上报了事件,但是应用层没读到上报的事件(或者经常没读到上报的事件)

上报事件代码

定时器超时处理函数如下,在超时函数中上报按键事件。

void key_drv_timer_handler( struct timer_list *timer )
{
    if ( !gpio_get_value( g_key.gpio_num ) )
        input_report_key( g_key.input_device, KEY_0, 0 );
    else
        input_report_key( g_key.input_device, KEY_0, 1 );
    input_sync( g_key.input_device );
}

原因

在调用 request_irq 申请中断时,只使能了下降沿中断(IRQF_TRIGGER_FALLING ),没有使能上升沿中断(IRQF_TRIGGER_RISING)。每次都是上报了按键为低的情况,input 子系统可能会以为按键的状态一直都是拉低,没弹起。

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gdut_llkkyy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值