【linux kernel】 中斷處理-中斷上半部

 

 

歡迎轉載,轉載時需保留做者信息,謝謝。 html

郵箱:tangzhongp@163.com linux

博客園地址:http://www.cnblogs.com/embedded-tzp windows

Csdn博客地址:http://blog.csdn.net/xiayulewa 數據結構

 

環境: http://www.cnblogs.com/embedded-tzp/p/4443876.html dom

 

 

1. arm硬件中斷

從頭介紹中斷原理太麻煩,通常來講看這篇文章的人對中斷必然已經有了必定的認識。無論哪款處理器,中斷的基本概念是同樣的:ide

中斷向量表。函數

中斷優先級。spa

中斷現場保護與恢復。.net

 

1.1. 中斷向量表

 

中斷向量表,程序發生中斷後會跳轉到該表執行,通常在裏面放置mov pc, addr_of_isr_func形式的指令,以中斷向量表爲跳板,跳轉到中斷服務程序中。指針

通常處理器中斷向量表地址是固定的,arm920t固定在0x00000000,或者0xFFFF0000處,其地址是經過配置CP15Register 1實現的。詳細可閱讀ARM920T_TRM1_S.pdf

默認中斷向量表是在0x00000000處,arm920t的中斷向量表以下:

clip_image002[4]

         clip_image004[4]

上圖爲arm中斷處理的流程,在程序正常運行時, 發生定時器中斷,跳轉到中斷向量表處執行對應指令,而irq中斷向量地址指令爲goto irq_isr, 跳轉到中斷irq中斷服務程序,此時首先保存現場,執行完中斷邏輯後,再恢復現場,後中斷返回,從以前被中斷處的下一條指令繼續運行。

 

 

 

1.2. Linux內核中的中斷向量表

entry-armv.S (src\arch\arm\kernel)中定義中斷向量表。

    .section .vectors, "ax", %progbits

__vectors_start:

    W(b)    vector_rst

    W(b)    vector_und

    W(ldr)  pc, __vectors_start + 0x1000

    W(b)    vector_pabt

    W(b)    vector_dabt

    W(b)    vector_addrexcptn

    W(b)    vector_irq

W(b)    vector_fiq

 

 

1.3. linux中斷初始化配置

 

硬件:有主中斷SRCPND,子中斷SUBSRCPND。主中斷也可稱爲父中斷。

 

處理器中斷初始化: MACHINE_STARTs3c2440_init_irq中初始化, 同時初始化static struct s3c_irq_intc *s3c_intc[3];變量

 

中斷(irq,abt,und)的堆棧初始化setup_arch→setup_processor→cpu_init→struct stack *stk = &stacks[cpu] (irq,abt,und)

 

映射中斷向量表:setup_arch→paging_init→devicemaps_init

 

定義中斷向量表:src\arch\arm\kernel\entry-armv.S(其大部分定義在entry-header.S (src\arch\arm\kernel))__vectors_start

 

中斷方式初始化:如上升沿等,在init_s3c2440base裏面定義

 

 

1.4. Linux中斷執行流程

1.4.1. 中斷入口與現場保護

假定程序運行在用戶態,中斷類型爲irq,則:

 

   中斷髮生→W(b)   vector_irq( vector_irq vector_stub irq, IRQ_MODE, 4定義)→執行宏vector_stub定義的vector_irq中斷服務程序, 定義見下:

    vector_stub irq, IRQ_MODE, 4

 

    .long   __irq_usr           @  0  (USR_26 / USR_32)

    .long   __irq_invalid           @  1  (FIQ_26 / FIQ_32)

    .long   __irq_invalid           @  2  (IRQ_26 / IRQ_32)

    .long   __irq_svc           @  3  (SVC_26 / SVC_32)

.long   __irq_invalid           @  4

 

vector_stub的做用是保存中斷現場,獲取中斷前處理器狀態,而後將狀態設置爲SVC mode,後跳轉到相應的中斷才處理程序。 前面假定中斷前爲用戶態,因此中斷髮生後,會最終跳轉到__irq_usr處執行。

1.4.2.    中斷服務程序

__irq_usr→irq_handler→handle_arch_irq(是個函數指針,全局變量=s3c24xx_handle_irq, s3c24xx_init_intc中被賦值)→s3c24xx_handle_intc→handle_IRQ→generic_handle_irqdesc->handle_irq若是是父中斷,則執行s3c_irq_demux(在s3c24xx_irq_map中設置,執行chained_irq_enter→irq_ack清除主中斷)→generic_handle_irq→desc->handle_irqhandle_edge_irqchip->irq_ack清除次級中斷相關位,在s3c24xx_irq_map中設置)→handle_irq_event→ handle_irq_event_percpu→action->handler(request_irq申請,循環處理action = action->next)

 

1.4.3.    中斷返回與現場恢復

__irq_usr爲例:b ret_to_user_from_irqentry-common.S (src\arch\arm\kernel)定義)→ work_pending (在entry-common.S (src\arch\arm\kernel)定義)→ do_work_pending→ schedule

 

 

handle_arch_irq賦值流程:MACHINE_STARTinit_irqs3c2440_init_irq→s3c24xx_init_intc→set_handle_irq

 

desc->handle_irq註冊流程:MACHINE_START::s3c2440_init_irq→s3c24xx_init_intc→irq_domain_add_legacy(傳入 

s3c24xx_irq_ops)ops->map(即s3c24xx_irq_ops->map,s3c24xx_irq_map→根據中斷類型若是是邊沿觸發,則 

desc->handle_irq=handle_edge_irq

 

 

 

    用到的變量與文件對應關係: 

src\arch\arm\include\asm\Unified.h: #define PSR_ISETSTATE 0

src\arch\arm\include\asm\linkage.h: #define ENDPROC(name) \

  .type name, %function; \

  END(name)

src\include\linux\linkage.h:#define END(name) \

  .size name, .-name

#endif

 

Asm-offsets.c (src\arch\arm\kernel):  DEFINE(S_FRAME_SIZE,    sizeof(struct pt_regs))

entry-header.S (src\arch\arm\kernel)) why .req   r8     @ Linux syscall (!= 0)

Unified.h (src\arch\arm\include\asm):#define BSYM(sym) sym

src\arch\arm\kernel\Asm-offsets.c: DEFINE(SYS_ERROR0,     0x9f0000);

 

1.5. linux中斷註冊

request_irq→request_threaded_irq→__setup_irq→new->irq = irq;   *old_ptr = new;old_ptr指向action鏈表的最後一項)

 

 

1.6. linux中斷地址映射

 

linux中斷地址分配:MACHINE_STARTmini2440_map_ios3c24xx_init_io →iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); // 該函數分析詳細見gpio章節。

clip_image005[4]

由上述可見,#define S3C_VA_IRQ  S3C_ADDR(0x00000000) irq虛擬地址爲0xF6000000,且由於串口物理地址和虛擬地址對應關係肯定了,irq物理地址和虛擬地址也肯定了,由於PA1-PA2 = VA1-VA2

 

1.7. linux中斷數據結構

 

clip_image006[4]

 

由上圖可見,中斷號能夠索引全部的中斷對象。

中斷概貌:最重要的結構是全局變量struct irq_desc irq_desc[NR_IRQS]; 每個中斷號對應一個struct irq_desc, MACHINE_START中的s3c2440_init_irq主要是初始化該結構體。每一箇中斷號和具體的irq_desc[i]對應,根據中斷號就能知道該中斷的全部信息,如該中斷是父中斷仍是子中斷,該中斷的處理函數。父中斷讀取子中斷源,經過desc->handle_irq = s3c_irq_demux(不必定是這個函數,爲了描述方便舉例的,後同)執行具體的子中斷函數,子中斷再執行desc->handle_irq = handle_edge_irq,最終都會

執行desc->action->handler 總結起來 desc->handle_irq是執行函數分配,desc->action->handler執行具體的中斷函數,

 

 1.4.  函數集合

request_irq

free_irq

相關文章
相關標籤/搜索