首先非常感谢陈莉君老师的赏识,题目名字也是陈老师帮忙起的。

大家好,我叫张昺华,中间那个字和“饼”字一个读音,嘿嘿,相信不少人都不认识我的第二个字吧,这是我一个很聪明的表哥(当时他只有9岁)从新华字典里取名的,光明正大的意思,希望我一生光明磊落。当时的技术不发达,加上这个字太特殊了,导致基本上大考都没我名字,就连户口本都是手写的……因为这个字也让我很容易上课被点名,因为太特别了,老师们总是喜欢叫上一叫……可是现在技术发达了,照样经常遇到很多人不认识这个字就会随便输入,比如说张锅华,张口华,张日华…有次在医院拿药,竟然有人把我的名字输入成了张菊花(泪奔…),不过可能因为它的特殊性吧,让我交到了非常多的好朋友,高中的230,大学的社联公关部,启明星支教队,电气2班,科创的小伙伴儿们以及现在公司里的很多朋友……

2014年我毕业于广东省惠州学院,我从小酷爱理科,当看到陈莉君老师在《Linux内核之旅》上发的学生在课堂上用课本剧的方式来诠释技术时,想到了自己初中的时候老师就是这样锻炼我们的,很喜欢那样的学习氛围,自己大学时和小伙伴们一起创立了科技创新协会,目的就是可以一群人在研究技术,一起做有意思的东西,一起分享技术带给我们的快乐,也希望中国有更多的人热爱技术,喜欢一起研究、分享技术,然后可以一起用我们的技术来做一些好玩的东西,可以为这个社会创造一些东西来改善人们的生活。

如下为本人原创,在解决问题的过程中的一点心得(要感谢公司的权哥与泉哥的鼎力支持),如果有描述不准确的地方还请各位指出,非常感谢

Linux内核版本:linux-4.9.18

曾有一次调试触摸屏的时候遇到如下的问题

/startup/modules#

[  233.370296] irq 44: nobody cared (try booting with the"irqpoll" option)

[ 233.376983] CPU: 0 PID: 0 Comm: swapper Tainted:G          O    4.9.18 #8

[ 233.383912] Hardware name: Broadcom Cygnus SoC

[ 233.388378] [<c010cbfc>] (unwind_backtrace) from [<c010a5fc>] (show_stack+0x10/0x14)

[ 233.396103] [<c010a5fc>] (show_stack) from [<c0145d38>](__report_bad_irq+0x24/0xa4)

[ 233.403821]

[<c0145d38>](__report_bad_irq) from [<c0145fdc>] (note_interrupt+0x1c8/0x274)

[ 233.412052]

[<c0145fdc>](note_interrupt) from [<c014400c>] (handle_irq_event_percpu+0x44/0x50)

[ 233.420715]

[<c014400c>](handle_irq_event_percpu) from [<c0144040>] (handle_irq_event+0x28/0x3c)

[ 233.429550]

[<c0144040>](handle_irq_event) from [<c0146574>] (handle_simple_irq+0x70/0x78)

[  233.437868]

[<c0146574>](handle_simple_irq) from [<c01438d8>] (generic_handle_irq+0x18/0x28)

[ 233.446366]

[<c01438d8>](generic_handle_irq) from [<c02adb3c>](iproc_gpio_irq_handler+0xd0/0x11c)

[ 233.455376]

[<c02adb3c>](iproc_gpio_irq_handler) from [<c01438d8>] (generic_handle_irq+0x18/0x28)

[ 233.464297]

[<c01438d8>](generic_handle_irq) from [<c0143980>] (__handle_domain_irq+0x80/0xa4)

[ 233.472959]

[<c0143980>](__handle_domain_irq) from [<c01013d0>] (gic_handle_irq+0x50/0x84)

[ 233.481275] [<c01013d0>] (gic_handle_irq) from [<c010b02c>](__irq_svc+0x6c/0x90)

[ 233.488723] Exception stack(0xc0901f60 to 0xc0901fa8)

[ 233.493754] 1f60: c0112900 c0717028 c0901fb8 00000000 c093af4c 0000000000000335 c0826220

[ 233.501896] 1f80: 00000001 414fc091 df9eab80 00000000 c0900038 c0901fb0c010843c c0108440

[ 233.510034] 1fa0: 60000013 ffffffff

[ 233.513514] [<c010b02c>] (__irq_svc) from [<c0108440>](arch_cpu_idle+0x2c/0x38)

[ 233.520887] [<c0108440>] (arch_cpu_idle) from [<c013a6ec>](cpu_startup_entry+0x50/0xc0)

[ 233.528956] [<c013a6ec>] (cpu_startup_entry) from [<c0800d70>](start_kernel+0x414/0x4b0)

[ 233.537097] handlers:

[ 233.539363]

[<c014408c>]irq_default_primary_handler threaded [<bf03ff68>] synaptics_rmi4_irq[synaptics_dsx]

[  233.549300]Disabling IRQ#44

首先我们顺着错误跟踪linux内核来看下

kernel/irq/spurious.c

因此有提示的log信息可以看出,是走的else的分支,

bad_action_ret(action_ret)返回为0

通过此函数的dump_stack的信息,可以追溯到调用者

drivers/pinctrl/bcm/pinctrl-iproc-gpio.c

kernel/irq/chip.c

handle_level_irq

===> handle_irq_event  (kernel/irq/handle.c)

===>handle_irq_event_percpu  (kernel/irq/handle.c)

===>__handle_irq_event_percpu  (kernel/irq/handle.c)

根据log,我们可以在下图看到note_interrupt,即说明noirqdebug=0

Kernel/irq/handle.c

因为上面我们已经分析过bad_action_ret(action_ret)返回为0

因此在note_interrupt函数里面只会从如下分支进去

Kernel/irq/spurious.c

从上图可以看出,如果想出现那样的错误,必须满足条件

desc->irqs_unhandled > 99900为真

如要要满足如上条件的话,那么只有如下地方会让irqs_unhandled++

Kernel/irq/spurious.c

通过上图,我们可以看到,必须满足条件:

action_ret == IRQ_NONE为真

再继续看回如下图,action_ret就是retval

res即为action_ret

而 action->handler的回调函数是:

request_threaded_irq线程化注册中断的第2个参数

kernel/irq/manage.c

因为handler为NULL,所以handler = irq_default_primary_handler

action_ret= IRQ_WAKE_THREAD

Kernel/irq/spurious.c

经过如上图,我们可以发现action_ret = IRQ_NONE

那么我们接下来看看到底是怎么被调用到这里的,一个中断的产生又是怎样的?

首先handle_level_irq这个函数是在这里注册到kernel中的

drivers/pinctrl/bcm/pinctrl-iproc-gpio.c

static intiproc_gpio_probe(struct platform_device *pdev)

===>gpiochip_irqchip_add

Include/linux/gpio/driver.h

typedef    void(*irq_flow_handler_t)(struct irq_desc *desc);

这里即gpiochip->irq_handler = handle_level_irq

struct irqaction *action;

一个中断开始的时候

arch/arm/kernel/entry-armv.S

这里有一个全局的handle_arch_irq

这个全局的handle_arch_irq会在如下地方被赋值

arch/arm/kernel/setup.c

void __init setup_arch(char**cmdline_p)

===> handle_arch_irq被赋值

那么接下来我们就要找到mdesc->handle_irq又是在哪里被赋值了呢?

drivers/irqchip/irq-gic.c

这里有这样的函数set_handle_irq

接下来我们看下这个函数的实现就知道了

arch/arm/kernel/irq.c

那么这个set_handle_irq又是在哪里被调用的呢?

针对内核版本Linux-4.9.18

drivers/irqchip/irq-gic.c

gic_of_init

===>__gic_init_bases

===>set_handle_irq

Include/linux/irqchip.h

Include/linux/of.h

Include/linux/of.h

因此我们得出一个结论:

handle_arch_irq = gic_handle_irq

一个中断开始后,从entry-armv.S中进入

handle_domain_irq

===> __handle_domain_irq

===>generic_handle_irq

===>generic_handle_irq_desc

这里的desc->handle_irq其实就是handle_level_irq

这里是如何转换过去的呢?

drivers/pinctrl/bcm/pinctrl-iproc-gpio.c

gpiochip_set_chained_irqchip

===>irq_set_chained_handler_and_data

===> __irq_do_set_handler

Kernel/irq/chip.c

回归到最初的问题,之前我们分析出如下的结论:

如果想出现log那样的错误,必须满足条件

desc->irqs_unhandled > 99900为真

如要要满足如上条件的话,那么只有让irqs_unhandled++

那么满足这个条件就必须action_ret== IRQ_NONE

#defineSPURIOUS_DEFERRED      0x80000000

如下图:

也就是必须要满足handled !=desc->threads_handled_last为假

这里handled= threads_handled

而desc->threads_handled_last会在如下位置设置为SPURIOUS_DEFERRED

再看下图

Kernel/irq/manage.c

Irq_thread

这里会一直将threads_handled++ ,这里handled =threads_handled

直到满足handled !=desc->threads_handled_last为假

那么为什么这个threads_handled会一直++呢?

因为这里:

上图是正确的修改,如果gpiochip_irqchip_add的第四个参数是handle_simple_irq的话,

那么就会出现threads_handled会一直++的情况,从而产生本文最开头的错误

[ 233.370296] irq44: nobody cared (try booting with the "irqpoll" option)

[ 233.549300] DisablingIRQ #44

这里我们就要对handle_simple_irq 与handle_level_irq做个分析了,具体的分析大家可以网上看蜗窝的资料以及csdn上很多对这块有详细的描述,我这里简单叙述下我个人的理解

首先上代码:

大家可以看出来,handle_simple_irq做的事情很简单,而handle_level_irq却做了这个动作

mask_ack_irq(desc);因为是电平中断,如果不做mask中断的动作的话,会因为中断电平一直是有效电平导致中断控制器会源源不断地给cpu发中断

而handle_simple_irq就是非常简单的处理中断,没有mask中断,原本代码是写的handle_simple_irq,而触摸屏的中断是设置为线程化的,并且为电平触发方式,那么如果没有mask该中断,那么当一次线程化中断处理函数还未执行完成的时候,又会有源源不断地中断一直进来,那么就会出现threads_handled会一直++的情况,从而产生本文最开头的错误

到此这个问题就已经分析完了

如下只是个小记录:

这个函数的作用是检查是否有中断嵌套

【作者】张昺华

【新浪微博】张昺华--sky

【博客园】 http://www.cnblogs.com/sky-heaven/

【知乎】 http://www.zhihu.com/people/zhang-bing-hua

【我的作品---旋转倒立摆】 http://v.youku.com/v_show/id_XODM5NDAzNjQw.html?spm=a2hzp.8253869.0.0&from=y1.7-2

【我的作品---自平衡自动循迹车】 http://v.youku.com/v_show/id_XODM5MzYyNTIw.html?spm=a2hzp.8253869.0.0&from=y1.7-2

参考:

http://www.wowotech.net/irq_subsystem/request_threaded_irq.html

http://www.wowotech.net/linux_kenrel/interrupt_descriptor.html

https://blog.csdn.net/tiantao2012/article/details/78062621

https://blog.csdn.net/tiantao2012/article/details/78094691

https://blog.csdn.net/zhao2272062978/article/details/70599978

https://blog.csdn.net/droidphone/article/details/7467436

https://blog.csdn.net/droidphone/article/details/7445825

https://blog.csdn.net/droidphone/article/category/1118447

https://blog.csdn.net/phenix_lord/article/details/45116259

https://blog.csdn.net/phenix_lord/article/details/45116595

https://blog.csdn.net/phenix_lord/article/details/45116689


本文最初发表于陈莉君老师的"Linux内核之旅"公众号。

一次触摸屏中断调试引发的深入探究相关推荐

  1. fiq中断的入口地址_嵌入式技巧:ARM的三种中断调试方法介绍

    嵌入式软件开发流程 参照嵌入式软件的开发流程.第一步:工程建立和配置.第二步:编辑源文件.第三步:工程编译和链接.第四步:软件的调试.第五步:执行文件的固化. 在整个流程中,用户首先需要建立工程并对工 ...

  2. 一次对K8S集群service的“非主流”访问方式引发的网络探究

    一次对K8S集群service的"非主流"访问方式引发的网络探究 目录 一次对K8S集群service的"非主流"访问方式引发的网络探究 (一)"颇有 ...

  3. RK3399 focaltech敦泰触摸屏移植调试

    CPU:RK3399 系统:Android 7.1 IC:FT5406 focaltech(敦泰)触摸屏也是比较常用的,但是相对汇顶,就比较少用 RK的源码中虽然有 focaltech 的代码,但没有 ...

  4. (20)Xilinx PCIE中断调试成功(学无止境)

    0 调试环境 FPGA与ARM通过PCIE接口进行数据交互.下位机为FPGA,上位机为ARM. 1 遇到问题 开发软件:vivado 2018.3 硬件型号:Xilinx K7/V7 FPGA FPG ...

  5. RK3288的GTxx触摸屏驱动调试

    电容屏是在LCD屏上覆盖一个透明的矩阵键盘,在调试goodix gt9xx系列触控屏的驱动时,会遇到各种问题! 1.linux启动时,触控屏驱动偶尔不能加载固件信息. 2.在使用过程中偶尔不能触发或触 ...

  6. RK3399 GT1X触摸屏驱动调试笔记

    硬件环境 1.Firefly AIO-3399(AI)开发版: 2.恒智的5寸电容触摸屏800X480,I2C驱动支持GT5688. 操作系统 Android 7.2 for rockship Ste ...

  7. 全志A64触摸屏驱动调试

    一.前言 linux的触摸屏驱动一般要经历一下几个步骤(以4412为例):1.移植驱动到linux源码"driver/input/touchscreen/"目录下,在Kconfig ...

  8. mini2440+jlink+mkd 裸机按键中断调试心得体会(2013.11.17已更新)

    开发板:友善之臂mini2440,仿真器:jlink v8,开发环境:RealView mdk 4.54 需要阅读的文档:S3C2440A_UserManual,mini2440开发手册,其他 实验目 ...

  9. Zynq-Linux移植学习笔记之52-国产ZYNQ standalone PL-PS中断调试

    1.背景介绍 目前采用国产ZYNQ替代进口xilinx ZYNQ,在调试PL-PS的中断时,和进口Xilinx ZYNQ有区别,记录如下. 2.vivado工程 直接引入一个GPIO输入ZYNQ PL ...

最新文章

  1. pandas dataframe中的列进行重新排序、倒排、正排、自定义排序详解及实践
  2. Typescript学习笔记(二)
  3. VS2010安装HTML5插件
  4. 超音速 启动_从根本上讲超音速亚原子Enterprise Java
  5. Spring构造函数依赖注入示例
  6. 微信小程序 Unexpected end of JSON input
  7. ztree 后台异步加载_zTree异步加载实现
  8. 2020 年百度之星#183;程序设计大赛 - 初赛三
  9. 初学必看,NFine框架结构加MVC快速开发平台登录流程梳理(附源码)
  10. 谷尼国际软件-企业竞争情报系统
  11. 2020年软件工程保研南大、国防科大、天大、同济、南开、北理、软件所、哈工大、哈工深、复旦经验分享
  12. 几个简单的小功能,能提高微信群活跃度?
  13. c语言程序商品的打折,C语言程序设计习题doc.doc
  14. 街头篮球服务器ip地域位置图,浅谈《街头篮球》韩服与国服六个位置的不同之处...
  15. linux中的xorg进程占用内存资源释放
  16. 编程求x的n次方_用C语言程序设计:求x的n次方的函数。
  17. win10下,更改程序磁贴图标
  18. 前端开发实战:实现京东购物平台的静态首页
  19. android实现上班打卡记录日历查看功能
  20. Mysql如何添加环境变量(详细教程)

热门文章

  1. java调用libreoffice_关于java使用libreoffice以及openoffice转换问题。
  2. 黑莓Curve 9360拥有NFC技术
  3. Windows 下编译 taglib
  4. 【成像】【1】Terahertz辐射
  5. 三星a9 刷 android 8,三星手机明年升级安卓8.0 新增功能曝光
  6. 一款能统计能存储日志设置超时时间的ping工具
  7. 【Python网络爬虫】Python网络爬虫案例:知乎Live
  8. 安卓 仿联系人索引列表 A到Z排序查询
  9. 计算机硬件报警声音,主板报警,详细教您电脑主板报警声的含义介绍
  10. 各种 RAID 详解