大发快3

嵌入式Linux热门培训内容之Linux中断申请

时间:2018-12-13 17:34:12

Linux中断还是很有必要去了解的,我们之前在项目上遇到因为中断引起的问题,在中断服务程序里面加上了休眠相关的代码引入的问题,大家在编写内核代码的时候,有必要注意一下。

一、中断注册方法

在linux内核中用于申请中断的函数是request_irq(),函数原型在Kernel/irq/manage.c中定义:

int request_irq(unsigned int irq, irq_handler_t handler,

                         unsigned long irqflags, const char *devname, void *dev_id)

cat /proc/interrupts中系统注册的中断

root@ubuntu:~/# cat /proc/interrupts 

            CPU0       

   0:         63   IO-APIC    2-edge      timer

   1:      12190   IO-APIC    1-edge      i8042

   8:          1   IO-APIC    8-edge      rtc0

   9:          0   IO-APIC    9-fasteoi   acpi

  12:      39472   IO-APIC   12-edge      i8042

  14:          0   IO-APIC   14-edge      ata_piix

  15:          0   IO-APIC   15-edge      ata_piix

  16:       2193   IO-APIC   16-fasteoi   vmwgfx, snd_ens1371

  17:    1374248   IO-APIC   17-fasteoi   ioc0

  19:      46282   IO-APIC   19-fasteoi   ens33

  24:          0   PCI-MSI 344064-edge      PCIe PME, pciehp

  25:          0   PCI-MSI 346112-edge      PCIe PME, pciehp

  26:          0   PCI-MSI 348160-edge      PCIe PME, pciehp

  27:          0   PCI-MSI 350208-edge      PCIe PME, pciehp

  28:          0   PCI-MSI 352256-edge      PCIe PME, pciehp

  29:          0   PCI-MSI 354304-edge      PCIe PME, pciehp

  30:          0   PCI-MSI 356352-edge      PCIe PME, pciehp

  31:          0   PCI-MSI 358400-edge      PCIe PME, pciehp

  32:          0   PCI-MSI 360448-edge      PCIe PME, pciehp

  33:          0   PCI-MSI 362496-edge      PCIe PME, pciehp

  34:          0   PCI-MSI 364544-edge      PCIe PME, pciehp

  35:          0   PCI-MSI 366592-edge      PCIe PME, pciehp

  36:          0   PCI-MSI 368640-edge      PCIe PME, pciehp

  37:          0   PCI-MSI 370688-edge      PCIe PME, pciehp

  38:          0   PCI-MSI 372736-edge      PCIe PME, pciehp

  39:          0   PCI-MSI 374784-edge      PCIe PME, pciehp

  40:          0   PCI-MSI 376832-edge      PCIe PME, pciehp

  41:          0   PCI-MSI 378880-edge      PCIe PME, pciehp

  42:          0   PCI-MSI 380928-edge      PCIe PME, pciehp

  43:          0   PCI-MSI 382976-edge      PCIe PME, pciehp

  44:          0   PCI-MSI 385024-edge      PCIe PME, pciehp

  45:          0   PCI-MSI 387072-edge      PCIe PME, pciehp

  46:          0   PCI-MSI 389120-edge      PCIe PME, pciehp

  47:          0   PCI-MSI 391168-edge      PCIe PME, pciehp

  48:          0   PCI-MSI 393216-edge      PCIe PME, pciehp

  49:          0   PCI-MSI 395264-edge      PCIe PME, pciehp

  50:          0   PCI-MSI 397312-edge      PCIe PME, pciehp

  51:          0   PCI-MSI 399360-edge      PCIe PME, pciehp

  52:          0   PCI-MSI 401408-edge      PCIe PME, pciehp

  53:          0   PCI-MSI 403456-edge      PCIe PME, pciehp

  54:          0   PCI-MSI 405504-edge      PCIe PME, pciehp

  55:          0   PCI-MSI 407552-edge      PCIe PME, pciehp

  56:      17991   PCI-MSI 1130496-edge      0000:02:05.0

  57:       4631   PCI-MSI 129024-edge      vmw_vmci

  58:          0   PCI-MSI 129025-edge      vmw_vmci

 NMI:          0   Non-maskable interrupts

 LOC:    2069188   Local timer interrupts

 SPU:          0   Spurious interrupts

 PMI:          0   Performance monitoring interrupts

 IWI:          0   IRQ work interrupts

 RTR:          0   APIC ICR read retries

 RES:          0   Rescheduling interrupts

 CAL:          0   Function call interrupts

 TLB:          0   TLB shootdowns

 TRM:          0   Thermal event interrupts

 THR:          0   Threshold APIC interrupts

 DFR:          0   Deferred Error APIC interrupts

 MCE:          0   Machine check exceptions

 MCP:        123   Machine check polls

 ERR:          0

 MIS:          0

 PIN:          0   Posted-interrupt notification event

 PIW:          0   Posted-interrupt wakeup event

在 2.4 内核和 2.6内核中都使用 request_irq() 函数来注册中断服务函数。

在 2.4 内核中,需要包含的头文件是 #include,

在 2.6 内核中需要包含的头文件则是#include。函数原型如下:

2.4 内核

int request_irq (unsignedintirq,void (*handler)(int,void*,structpt_regs*),unsignedlongfrags,constchar*device,void*dev_id);

2.6 内核

request_irq(unsignedintirq,irq_handler_thandler,unsignedlongflags,constchar*name,void*dev);

参数说明:

第一个参数:irq中断号,是一个整型

第二个参数:handler 中断服务函数,request_irq就是把中断服务函数注册到内核中

第 3 个参数 : flags指定了快速中断或中断共享等中断处理属性。具体参照: linux/interrupt.h

IRQF_DISABLED :当设置该标志时,会使Linux内核在执行中断处理函数时禁止所有的中断,如果未设置该标志,除了当前处理的中断外,中断处理函数可以被其他任何的中断打断,大多数中断处理函数都不需要设置这个标志,因为在执行中断处理函数时禁止所有中断是一种非常不好的内核编程方式。

IRQF_SHARED :该标志指定了 多个中断处理程序可以使用同一个中断线,在同一个中断线上注册的每一个中断处理程序必须指定该标志,否则每一个中断线上只有一个处理程序。

IRQF_SAMPLE_RANDOM:该标志表明这个设备产生的中断对内核池(entropy pool )有贡献,内核池负责提供从各种随机事件导出真正的随机数,如果指定了该标志,那么来自该设备的中断间隔时间就会作为熵填充到熵池,如果发出中断请求的设备以预知的速率产生中断(如系统定时器),或者受到某些外部因素影响(如联网设备收到人为的控制),那么认为这种设备申请中断处理函数时就不要设置这个标志,而对于那些以不可预知的速率产生中断的设备而言,就是一种很好的熵源。

第 4 个参数: name 通常是设备驱动程序的名称。改值用在 /proc/interrupt 系统 (虚拟) 文件上,或内核发生中断错误时使用。

第 5 个参数 :dev_id 中断名称 可作为共享中断时的中断区别参数,也可以用来指定中断服务函数需要参考的数据地址。建议将设备结构指针作为dev_id参数

二、中断注销方法

注销函数定义在Kernel/irq/manage.c中定义: 

    void free_irq(unsigned int irq, void *dev_id)

返回值:

函数运行正常时返回 0 ,否则返回对应错误的负值。

三、问题

在项目上有个问题,开机的时候提示有一大段错误日志,如下

[ 30.935691] irq 120: nobody cared (try booting with the "irqpoll" option)

[ 30.935731] CPU: 0 PID: 174 Comm: irq/120-rk808 Not tainted 4.4.83 #7

[ 30.935739] Hardware name: Rockchip RK3399 Excavator Board edp (Android) (DT)

[ 30.935749] Call trace:

[ 30.935768] [<ffffff800808967c>] dump_backtrace+0x0/0x1cc

[ 30.935778] [<ffffff800808985c>] show_stack+0x14/0x1c

[ 30.935789] [<ffffff8008373838>] dump_stack+0x94/0xb4

[ 30.935800] [<ffffff80080f6c34>] __report_bad_irq+0x38/0xd8

[ 30.935809] [<ffffff80080f6f74>] note_interrupt+0x1dc/0x280

[ 30.935818] [<ffffff80080f45ac>] handle_irq_event_percpu+0x1dc/0x26c

[ 30.935826] [<ffffff80080f4680>] handle_irq_event+0x44/0x74

[ 30.935835] [<ffffff80080f7ac4>] handle_level_irq+0xcc/0x104

[ 30.935843] [<ffffff80080f3adc>] generic_handle_irq+0x1c/0x2c

[ 30.935855] [<ffffff80083abb5c>] rockchip_irq_demux+0xe0/0x188

[ 30.935863] [<ffffff80080f3adc>] generic_handle_irq+0x1c/0x2c

[ 30.935871] [<ffffff80080f3df8>] __handle_domain_irq+0x80/0xac

[ 30.935879] [<ffffff8008080ef8>] gic_handle_irq+0xbc/0x154

[ 30.935887] Exception stack(0xffffffc07b0b7be0 to 0xffffffc07b0b7d10)

[ 30.935897] 7be0: ffffffc07bceea9c 00000000000093e8 ffffff800807e000 0000000000000000

[ 30.935906] 7c00: 0000000000000000 ffffff8008530d24 0000000000000001 00000000bfd4d5ba

[ 30.935915] 7c20: ffffffc07b09b0a0 ffffffc07b0b7950 0000000000000940 0000000000100011

[ 30.935923] 7c40: 00000000f44ea948 00000000d3bbfc28 00000000f44c9c3b 0000000000000000

[ 30.935932] 7c60: 0000000000000000 0000000000000000 0000000000000000 ffffffc07bceea00

[ 30.935941] 7c80: ffffffc07bceea9c ffffffc07b08a800 ffffffc07bceea20 ffffff80093806ad

[ 30.935950] 7ca0: ffffffc07b08a840 ffffffc07b09a700 0000000000000001 ffffffc07b09a700

[ 30.935960] 7cc0: ffffffc07b09a700 ffffffc07b0b7d10 ffffff80080f508c ffffffc07b0b7d10

[ 30.935969] 7ce0: ffffff8008beb648 0000000060400145 ffffffc07bceea00 ffffffc07b00b800

[ 30.935976] 7d00: ffffffffffffffff ffffff80080f5084

[ 30.935984] [<ffffff8008082160>] el1_irq+0xe0/0x170

[ 30.935995] [<ffffff8008beb648>] _raw_spin_unlock_irq+0x18/0x40

[ 30.936005] [<ffffff80080f508c>] irq_finalize_oneshot.part.39+0xa4/0xc8

[ 30.936013] [<ffffff80080f5104>] irq_thread_fn+0x54/0x68

[ 30.936021] [<ffffff80080f52e0>] irq_thread+0x104/0x1dc

[ 30.936030] [<ffffff80080bc474>] kthread+0xe8/0xf0

[ 30.936038] [<ffffff80080828d0>] ret_from_fork+0x10/0x40

[ 30.936044] handlers:

[ 30.936051] [<ffffff80080f46b0>] irq_default_primary_handler threaded [<ffffff800853669c>] regmap_irq_thread

[ 30.936067] Disabling IRQ #120

里面有个Disabling IRQ #120,通过cat /proc/interrupts  查找是哪个??榈闹卸?,对应找到申请的代码,然后对应看看原理图是否匹配上。

最后发现这个GPIO口没有用到,导致异常日志。

?

免责声明: 本站资料及图片来源互联网文章,本网不承担任何由内容信息所引起的争议和法律责任。所有作品版权归原创作者所有,与本站立场无关,如用户分享不慎侵犯了您的权益,请联系我们告知,我们将做删除处理!