Linux下xl9535 gpio扩展芯片bug调试

文章目录

1、环境介绍

这段时间在rk3576下调试ec11旋转编码器时(ec11旋转编码器的调试可以参考《Linux下EC11旋转编码器驱动调试》),发现刚上电时,是可以使用的,但大概不到一分钟左右,就没反应了,同时内核有如下打印:

在此先介绍一下硬件连接,我的ec11是连接到一个xl9535 gpio扩展芯片,而非rk3576的原生IO。下图展示了之间的连接关系:

当xl9535的IO引脚有状态变化时,RK3576的gpio4_A6脚就会收到xl9535 INT_脚的一个低电平输出作为中断信号。

下面再给出伪设备树便于大家理解之间的连接关系:

c 复制代码
gpio4: gpio@2ae40000 {
    compatible = "rockchip,gpio-bank";
    reg = <0x0 0x2ae40000 0x0 0x200>;
    interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru PCLK_GPIO4>, <&cru DBCLK_GPIO4>;

    gpio-controller;
    #gpio-cells = <2>;
    gpio-ranges = <&pinctrl 0 128 32>;
    interrupt-controller;
    #interrupt-cells = <2>;
};

xl9535: xl9535@21 {
    compatible = "nxp,pca9535";
    reg = <0x21>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_xl9535>;
    gpio-controller;
    #gpio-cells = <2>;
    interrupt-parent = <&gpio4>;
    interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
    #interrupt-cells = <2>;
    interrupt-controller;
};

Coder_A {
    compatible = "gpio-keys";
    status = "okay";
    #address-cells = <1>;
    #size-cells = <0>;
    coder_A {
        label = "coder_A";
        linux,code=<250>;
        debounce-interval = <0>;
        gpios = <&xl9535 12 GPIO_ACTIVE_HIGH>;
        interrupt-parent = <&xl9535>;
        interrupts = <12 IRQ_TYPE_EDGE_RISING>;
    };
};

Coder_B {
    compatible = "gpio-keys";
    status = "okay";
    #address-cells = <1>;
    #size-cells = <0>;
    coder_B {
        label = "coder_B";
        linux,code=<251>;
        debounce-interval = <0>;
        gpios = <&xl9535 13 GPIO_ACTIVE_HIGH>;
        interrupt-parent = <&xl9535>;
        interrupts = <13 IRQ_TYPE_EDGE_RISING>;
    };
};

2、结论

这里先给出结论,是因为xl9535的INT_脚没有接上拉电阻导致INT_脚输出一直为0v,相当于gpio4_A6中断源一直收到中断信号,最后因无效中断次数超过了99900次,内核将gpio4_A6中断源对应的中断处理函数(xl9535的中断函数)关闭,导致ec11旋转编码器用不了。

3、分析

上面说到,当开机不到1分钟左右,就会打印如下的错误信息:

shell 复制代码
[  340.968820] irq 70: nobody cared (try booting with the "irqpoll" option)
[  340.969082] handlers:
[  340.969090] [<0000000074d089d2>] irq_default_primary_handler threaded [<00000000eb0f1cb4>] pca953x_irq_handler
[  340.969112] Disabling IRQ #70

全局查找发现,是在spurious.c的__report_bad_irq()函数中打印该提示:

再看看是哪个函数调用的__report_bad_irq(),最后发现是note_interrupt()。因note_interrupt()函数过长,这里截取部分内容:

重点就是图中的time_after()函数,该函数用于判断两次中断之间的时间间隔,如果小于一定的时间,则无效次数累加。当无效次数超过99900次,关闭该中断。

上面是反向跟踪,下面正向跟踪,即从xl9535的中断函数入手。xl9535使用的驱动函数文件为gpio-pca953x.c,从这个错误信息可以快速知道中断函数名为pca953x_irq_handler():

继续进入handle_nested_irq():

最终在该函数又回到了note_interrupt():

所以此时可以怀疑,是不是xl9535的INT_脚一直输出低电平,导致频繁触发xl9535中断函数,最终被关闭。

然后实际测量gpio4_A6发现确实一直是0v,再来看看xl9535的数据手册对INT_脚的描述:

INT_脚是开漏输出,需要通过一个上拉电阻连接到Vcc。然而查看xl9535相关原理图发现INT_脚确实没有上拉。

4、解决

最后通过飞线,将xl9535的INT_脚接一颗10k上拉电阻到Vcc,此时中断数不会再一直累加:

5、总结

参考文章:

irq: nobody cared (try booting with the "irqpoll" option)_nobody cared (try booting with the "irqpoll" optio-CSDN博客

相关推荐
Wang's Blog26 分钟前
Linux小课堂: Vim与Emacs之Linux文本编辑器的双雄格局及Vim安装启动详解
linux·vim·emacs
观山岳五楼27 分钟前
unbuntu系统配置IPV6的三种模式
linux·服务器·ip·1024程序员节
运维行者_1 小时前
AWS云服务故障复盘——从故障中汲取的 IT 运维经验
大数据·linux·运维·服务器·人工智能·云计算·aws
王道长服务器 | 亚马逊云1 小时前
AWS Systems Manager:批量服务器管理的隐藏利器
linux·网络·云计算·智能路由器·aws
命运之光2 小时前
【快速解决】Linux服务器安装Java17运行环境
linux·运维·服务器
你喜欢喝可乐吗?2 小时前
Ubuntu服务器无法显示命令行登录提示
linux·运维·服务器·ubuntu
FJW0208142 小时前
【Linux】用户管理及优化
linux·运维·服务器
---学无止境---2 小时前
Linux中内核和用户空间通信send_uevent函数的实现
linux·网络
艾莉丝努力练剑3 小时前
【C++:继承】C++面向对象继承全面解析:派生类构造、多继承、菱形虚拟继承与设计模式实践
linux·开发语言·c++·人工智能·stl·1024程序员节
报错小能手3 小时前
项目——基于C/S架构的预约系统平台(3)
linux·开发语言·笔记·学习·架构·1024程序员节