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博客

相关推荐
Willis_m7 分钟前
Linux 服务器用 SSH 拉取多个 Git 工程
linux·服务器·git·ssh
紫金修道14 分钟前
【Linux】在Arm服务器源码编译onnxruntime-gpu的whl
linux·服务器·arm开发
xq5148632 小时前
Linux系统下安装mongodb
linux·mongodb
柒七爱吃麻辣烫2 小时前
在Linux中安装JDK并且搭建Java环境
java·linux·开发语言
孤寂大仙v2 小时前
【Linux笔记】——进程信号的产生
linux·服务器·笔记
深海蜗牛3 小时前
Jenkins linux安装
linux·jenkins
愚戏师3 小时前
Linux复习笔记(三) 网络服务配置(web)
linux·运维·笔记
JANYI20183 小时前
嵌入式MCU和Linux开发哪个好?
linux·单片机·嵌入式硬件
熊大如如4 小时前
Java NIO 文件处理接口
java·linux·nio
晚秋大魔王4 小时前
OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——nettle库
linux·开源·harmonyos