嵌入式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中系統注冊的中斷

[email protected]:~/# 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口沒有用到,導致異常日志。

? 江苏快3号码表