arm linux內(nèi)核中ARM中斷實現(xiàn)詳解_第1頁
arm linux內(nèi)核中ARM中斷實現(xiàn)詳解_第2頁
arm linux內(nèi)核中ARM中斷實現(xiàn)詳解_第3頁
arm linux內(nèi)核中ARM中斷實現(xiàn)詳解_第4頁
arm linux內(nèi)核中ARM中斷實現(xiàn)詳解_第5頁
已閱讀5頁,還剩10頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、linux-2.6.26內(nèi)核中ARM中斷實現(xiàn)詳解(1) 作者:劉洪濤,華清遠見嵌入式學(xué)院金牌講師,ARM ATC授權(quán)培訓(xùn)講師??戳艘恍┚W(wǎng)絡(luò)上關(guān)于linux中斷實現(xiàn)的文章,感覺有一些寫的非常好,在這里首先感謝他們的無私付出,然后也想再補充自己對一些問題的理解。先從函數(shù)注冊引出問題吧。一、中斷注冊方法在linux內(nèi)核中用于申請中斷的函數(shù)是request_irq(),函數(shù)原型在Kernel/irq/manage.c中定義:int request_irq(unsigned int irq, irq_handler_t handler,     

2、0;                   unsigned long irqflags, const char *devname, void *dev_id)irq是要申請的硬件中斷號。handler是向系統(tǒng)注冊的中斷處理函數(shù),是一個回調(diào)函數(shù),中斷發(fā)生時,系統(tǒng)調(diào)用這個函數(shù),dev_id參數(shù)將被傳遞給它。irqflags是中斷處理的屬性,若設(shè)置了IRQF_DISABLED (老版本中的SA_INTERRUPT,本版zh

3、on已經(jīng)不支持了),則表示中斷處理程序是快速處理程序,快速處理程序被調(diào)用時屏蔽所有中斷,慢速處理程 序不屏蔽;若設(shè)置了IRQF_SHARED (老版本中的SA_SHIRQ),則表示多個設(shè)備共享中斷,若設(shè)置了IRQF_SAMPLE_RANDOM(老版本中的 SA_SAMPLE_RANDOM),表示對系統(tǒng)熵有貢獻,對系統(tǒng)獲取隨機數(shù)有好處。(這幾個flag是可以通過或的方式同時使用的)dev_id在中斷共享時會用到,一般設(shè)置為這個設(shè)備的設(shè)備結(jié)構(gòu)體或者NULL。devname設(shè)置中斷名稱,在cat /proc/interrupts中可以看到此名稱。request_irq()返回0表示成功,返回-INV

4、AL表示中斷號無效或處理函數(shù)指針為NULL,返回-EBUSY表示中斷已經(jīng)被占用且不能共享。關(guān)于中斷注冊的例子,大家可在內(nèi)核中搜索下request_irq。在編寫驅(qū)動的過程中,比較容易產(chǎn)生疑惑的地方是:1、中斷向量表在什么位置?是如何建立的?        2、從中斷開始,系統(tǒng)是怎樣執(zhí)行到我自己注冊的函數(shù)的?        3、中斷號是如何確定的?對于硬件上有子中斷的中斷號如何確定?      &#

5、160; 4、中斷共享是怎么回事,dev_id的作用是?本文以2.6.26內(nèi)核和S3C2410處理器為例,為大家講解這幾個問題。二、異常向量表的建立在ARM V4及V4T以后的大部分處理器中,中斷向量表的位置可以有兩個位置:一個是0,另一個是0xffff0000??梢酝ㄟ^CP15協(xié)處理器c1寄存器中V位(bit13)控制。V和中斷向量表的對應(yīng)關(guān)系如下:V=0                0x000000000x0000001C  &#

6、160;     V=1                0xffff00000xffff001Carch/arm/mm/proc-arm920.S中.section ".text.init", #alloc, #execinstr        _arm920_setup:    

7、0;   orr       r0, r0, #0x2100              .1. .1 .11 .1/bit13=1 中斷向量表基址為0xFFFF0000。R0的值將被付給CP15的C1.在linux中,向量表建立的函數(shù)為:init/main.c->start_kernel()->trap_init()void _init trap_init(void)

8、0;                        unsigned long vectors = CONFIG_VECTORS_BASE;                     

9、;             memcpy(void *)vectors, _vectors_start, _vectors_end - _vectors_start);                memcpy(void *)vectors + 0x200, _stubs_start, _stubs_end - _stubs_

10、start);                 .        在2.6.26內(nèi)核中CONFIG_VECTORS_BASE最初是在各個平臺的配置文件中設(shè)定的,如:arch/arm/configs/s3c2410_defconfig中CONFIG_VECTORS_BASE=0xffff0000_vectors_end 至 _vectors_start之間為異常向量表。

11、位于arch/arm/kernel/entry-armv.S.globl _vectors_start_vectors_start:        swi SYS_ERROR0:        b vector_und + stubs_offset /復(fù)位異常:        ldr pc, .LCvswi + stubs_offset    &#

12、160;   /未定義指令異常:        b vector_pabt + stubs_offset        /軟件中斷異常:        b vector_dabt + stubs_offset        /數(shù)據(jù)異常:     &#

13、160;  b vector_addrexcptn + stubs_offset        /保留:        b vector_irq + stubs_offset        /普通中斷異常:        b vector_fiq + stubs_offset   

14、;     /快速中斷異常:        .globl _vectors_end:_vectors_end:_stubs_end 至 _stubs_start之間是異常處理的位置。也位于文件arch/arm/kernel/entry-armv.S中。vector_und、vector_pabt、vector_irq、vector_fiq都在它們中間。stubs_offset值如下:.equ stubs_offset, _vectors_start + 0x200 - _stubs_s

15、tartstubs_offset是如何確定的呢?(引用網(wǎng)絡(luò)上的一段比較詳細的解釋)當匯編器看到B指令后會把要跳轉(zhuǎn)的標簽轉(zhuǎn)化為相對于當前PC的偏移量(±32M)寫入指令碼。從上面的代碼可以看到中斷向量表和stubs都發(fā)生了 代碼搬移,所以如果中斷向量表中仍然寫成b vector_irq,那么實際執(zhí)行的時候就無法跳轉(zhuǎn)到搬移后的vector_irq處,因為指令碼里寫的是原來的偏移量,所以需要把指令碼中的偏移量寫 成搬移后的。我們把搬移前的中斷向量表中的irq入口地址記irq_PC,它在中斷向量表的偏移量就是irq_PC-vectors_start, vector_irq在stubs中的偏移

16、量是vector_irq-stubs_start,這兩個偏移量在搬移前后是不變的。搬移后 vectors_start在0xffff0000處,而stubs_start在0xffff0200處,所以搬移后的vector_irq相對于中斷 向量中的中斷入口地址的偏移量就是,200+vector_irq在stubs中的偏移量再減去中斷入口在向量表中的偏移量,即200+ vector_irq-stubs_start-irq_PC+vectors_start = (vector_irq-irq_PC) + vectors_start+200-stubs_start,對于括號內(nèi)的值實際上就是中斷向量表中寫

17、的vector_irq,減去irq_PC是由匯 編器完成的,而后面的 vectors_start+200-stubs_start就應(yīng)該是stubs_offset,實際上在entry-armv.S中也是這樣定義的。三、中斷處理過程 這一節(jié)將以S3C2410為例,描述linux-2.6.26內(nèi)核中,從中斷開始,中斷是如何一步一步執(zhí)行到我們注冊函數(shù)的。 3.1 中斷向量表 archarmkernelentry-armv.S_vectors_start:            

18、60;swi SYS_ERROR0             b    vector_und + stubs_offset             ldr pc, .LCvswi + stubs_offset        

19、0;    b    vector_pabt + stubs_offset             b    vector_dabt + stubs_offset             b    vector

20、_addrexcptn + stubs_offset             b    vector_irq + stubs_offset              b    vector_fiq + stubs_offset    

21、60;        .globl   _vectors_end        _vectors_end:中斷發(fā)生后,跳轉(zhuǎn)到b vector_irq + stubs_offset的位置執(zhí)行。注意現(xiàn)在的向量表的初始位置是0xffff0000。 3.2 中斷跳轉(zhuǎn)的入口位置 archarmkernelentry-armv.S      .globl &#

22、160; _stubs_start    _stubs_start:     /*     * Interrupt dispatcher     */             vector_stub    irq, IRQ_MODE, 4 IRQ_MODE在includ

23、easmptrace.h中定義:0x12             .long    _irq_usr 0 (USR_26 / USR_32)             .long    _irq_invalid 1 (FIQ_26 / FIQ_32)  

24、0;          .long    _irq_invalid 2 (IRQ_26 / IRQ_32)             .long    _irq_svc 3 (SVC_26 / SVC_32)        

25、0;    .long    _irq_invalid 4             .long    _irq_invalid 5             .long    _irq_invalid 6

26、0;            .long    _irq_invalid 7             .long    _irq_invalid 8            

27、 .long    _irq_invalid 9             .long _irq_invalid a             .long _irq_invalid b          

28、   .long _irq_invalid c             .long _irq_invalid d             .long _irq_invalid e           

29、  .long _irq_invalid f上面代碼中vector_stub宏的定義為: .macro vector_stub, name, mode, correction=0             .align 5        vector_name:         &

30、#160;   .if correction             sub lr, lr, #correction             .endif             

31、              Save r0, lr_<exception> (parent PC) and spsr_<exception>              (parent CPSR)          &

32、#160;               stmia sp, r0, lr save r0, lr             mrs lr, spsr             str lr, s

33、p, #8 save spsr                           Prepare for SVC32 mode. IRQs remain disabled.              

34、;            mrs r0, cpsr             eor r0, r0, #(mode SVC_MODE)             msr spsr_cxsf, r0 為后面進入svc模式做準備

35、               the branch table must immediately follow this code                           and lr, lr, #

36、0x0f 進入中斷前的mode的后4位              #define USR_MODE 0x00000010             #define FIQ_MODE 0x00000011           

37、0; #define IRQ_MODE 0x00000012             #define SVC_MODE 0x00000013             #define ABT_MODE 0x00000017         &

38、#160;   #define UND_MODE 0x0000001b             #define SYSTEM_MODE 0x0000001f             mov r0, sp         

39、    ldr lr, pc, lr, lsl #2 如果進入中斷前是usr,則取出PC+4*0的內(nèi)容,即_irq_usr 如果進入中斷前是svc,則取出PC+4*3的內(nèi)容,即_irq_svc             movs pc, lr 當指令的目標寄存器是PC,且指令以S結(jié)束,則它會把 spsr的值恢復(fù)給cpsr branch to handler in SVC mode   &#

40、160;         .endm             .globl _stubs_start       _stubs_start:       /*       

41、;* Interrupt dispatcher       */             vector_stub irq, IRQ_MODE, 4             .long _irq_usr 0 (USR_26 / USR_32)  

42、60;          .long _irq_invalid 1 (FIQ_26 / FIQ_32)             .long _irq_invalid 2 (IRQ_26 / IRQ_32)             .long

43、 _irq_svc 3 (SVC_26 / SVC_32)用“irq, IRQ_MODE, 4”代替宏vector_stub中的“name, mode, correction”,找到了我們中斷處理的入口位置為vector_irq(宏里面的vector_name)。 從上面代碼中的注釋可以看出,根據(jù)進入中斷前的工作模式不同,程序下一步將跳轉(zhuǎn)到_irq_usr 、或_irq_svc等位置。我們先選擇_irq_usr作為下一步跟蹤的目標。 3.3 _irq_usr的實現(xiàn) archarmkernelentry-armv.S_irq_usr:     &

44、#160;       usr_entry 后面有解釋              kuser_cmpxchg_check       #ifdef CONFIG_TRACE_IRQFLAGS           

45、0; bl trace_hardirqs_off       #endif             get_thread_info tsk 獲取當前進程的進程描述符中的成員變量thread_info的地址,并將該地址保存到寄存器tsk等于r9(在entry-header.S中定義)       #ifdef CONFI

46、G_PREEMPT/如果定義了搶占,增加搶占數(shù)值              ldr r8, tsk, #TI_PREEMPT get preempt count             add r7, r8, #1 increment it        &#

47、160;    str r7, tsk, #TI_PREEMPT       #endifirq_handler 中斷處理,我們最關(guān)心的地方,3.4節(jié)有實現(xiàn)過程。       #ifdef CONFIG_PREEMPT             ldr r0, tsk, #TI_PREEMPT

48、0;            str r8, tsk, #TI_PREEMPT             teq r0, r7             strne r0, r0, -r0   &

49、#160;  #endif      #ifdef CONFIG_TRACE_IRQFLAGS             bl trace_hardirqs_on       #endifmov why, #0b ret_to_user 中斷處理完成,返回中斷產(chǎn)生的位置,3.7節(jié)有實現(xiàn)過程 上面代碼中的usr_entry

50、是一個宏,主要實現(xiàn)了將usr模式下的寄存器、中斷返回地址保存到堆棧中。.macro usr_entry       sub sp, sp, #S_FRAME_SIZE S_FRAME_SIZE的值在archarmkernelasm-offsets.c        中定義 DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs);實際上等于72     stmib sp, r1

51、 - r12             ldmia r0, r1 - r3             add r0, sp, #S_PC here for interlock avoidance            

52、60;mov r4, #-1 "" "" "" ""             str r1, sp save the "real" r0 copied              from the exception stack &

53、#160;                 We are now ready to fill in the remaining blanks on the stack:                      

54、0;    r2 - lr_<exception>, already fixed up for correct return/restart              r3 - spsr_<exception>              r4 - orig_r0 (see pt_reg

55、s definition in ptrace.h)                           Also, separately save sp_usr and lr_usr             &

56、#160;            stmia r0, r2 - r4             stmdb r0, sp, lr                  

57、0; Enable the alignment trap while in kernel mode             alignment_trap r0                   Clear FP to mark the first stack frame 

58、60;                        zero_fp             .endm上面的這段代碼主要在填充結(jié)構(gòu)體pt_regs ,這里提到的struct pt_regs,在include/asm/ptrace

59、.h中定義。此時sp指向struct pt_regs。       struct pt_regs                           long uregs18;        

60、0;           #define ARM_cpsr uregs16       #define ARM_pc uregs15       #define ARM_lr uregs14       #define ARM_sp uregs13  

61、0;    #define ARM_ip uregs12       #define ARM_fp uregs11       #define ARM_r10 uregs10       #define ARM_r9 uregs9       #define ARM_r8 ure

62、gs8       #define ARM_r7 uregs7       #define ARM_r6 uregs6       #define ARM_r5 uregs5       #define ARM_r4 uregs4       #de

63、fine ARM_r3 uregs3       #define ARM_r2 uregs2       #define ARM_r1 uregs1       #define ARM_r0 uregs0       #define ARM_ORIG_r0 uregs173.4 irq_handler的實現(xiàn)過程,arc

64、harmkernelentry-armv.S  .macro irq_handler              get_irqnr_preamble r5, lr              在include/asm/arch-s3c2410/entry-macro.s中定義了宏get_irqnr_p

65、reamble為空操作,什么都不做              1: get_irqnr_and_base r0, r6, r5, lr 判斷中斷號,通過R0返回,3.5節(jié)有實現(xiàn)過程               movne r1, sp       &

66、#160;                     routine called with r0 = irq number, r1 = struct pt_regs *                   &#

67、160;        adrne lr, 1b              bne asm_do_IRQ 進入中斷處理。                       .e

68、ndm3.5 get_irqnr_and_base中斷號判斷過程,include/asm/arch-s3c2410/entry-macro.s.macro get_irqnr_and_base, irqnr, irqstat, base, tmp              mov base, #S3C24XX_VA_IRQ           &#

69、160;   try the interrupt offset register, since it is there              ldr irqstat, base, #INTPND               teq irqstat, #0   

70、60;          beq 1002f              ldr irqnr, base, #INTOFFSET 通過判斷INTOFFSET寄存器得到中斷位置               mov tmp,

71、#1              tst irqstat, tmp, lsl irqnr              bne 1001f               the numbe

72、r specified is not a valid irq, so try               and work it out for ourselves              mov irqnr, #0 start here      

73、0;        work out which irq (if any) we got              movs tmp, irqstat, lsl#16              addeq irqnr, irqnr, #16 

74、;             moveq irqstat, irqstat, lsr#16              tst irqstat, #0xff              addeq

75、 irqnr, irqnr, #8              moveq irqstat, irqstat, lsr#8              tst irqstat, #0xf           

76、60;  addeq irqnr, irqnr, #4              moveq irqstat, irqstat, lsr#4              tst irqstat, #0x3        &

77、#160;     addeq irqnr, irqnr, #2              moveq irqstat, irqstat, lsr#2              tst irqstat, #0x1     

78、;         addeq irqnr, irqnr, #1               we have the value      1001:       adds irqnr, irqnr, #IRQ_EINT0 加上中斷號的基準

79、 數(shù)值,得到最終的中斷號,注意:此時沒有考慮子中斷的具體情況,(子中斷的問題后面會有講解)。IRQ_EINT0在include/asm/arch- s3c2410/irqs.h中定義.從這里可以看出,中斷號的具體值是有平臺相關(guān)的代碼決定的,和硬件中斷掛起寄存器中的中斷號是不等的。 1002:               exit here, Z flag unset if IRQ      

80、60;   .endm3.6 asm_do_IRQ實現(xiàn)過程,arch/arm/kernel/irq.c asmlinkage void _exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)                      struct pt_regs *old_regs

81、 = set_irq_regs(regs);              struct irq_desc *desc = irq_desc + irq;/根據(jù)中斷號找到對應(yīng)的irq_desc              /*        &#

82、160;     * Some hardware gives randomly wrong interrupts. Rather              * than crashing, do something sensible.              */&#

83、160;             if (irq >= NR_IRQS)              desc = &bad_irq_desc;              irq

84、_enter();/沒做什么特別的工作,可以跳過不看               desc_handle_irq(irq, desc);/ 根據(jù)中斷號和desc進入中斷處理               /* AT91 specific workaround */     

85、;         irq_finish(irq);              irq_exit();              set_irq_regs(old_regs);    

86、60;  static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc)                              desc->handle_irq(irq, desc)

87、;/中斷處理           上述asmlinkage void _exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)使用了asmlinkage標識。那么這個標識的含義如何理解呢? 該符號定義在kernel/include/linux/linkage.h中,如下所示: #include <asm/linkage.h>/各個具體處理器在此文件中定義asmlinkage    

88、;    #ifdef _cplusplus        #define CPP_ASMLINKAGE extern "C"        #else        #define CPP_ASMLINKAGE       &#

89、160;#endif#ifndef asmlinkage/如果以前沒有定義asmlinkage        #define asmlinkage CPP_ASMLINKAGE        #endif對于ARM處理器的<asm/linkage.h>,沒有定義asmlinkage,所以沒有意義(不要以為參數(shù)是從堆棧傳遞的,對于ARM平臺來說還是符合ATPCS過程調(diào)用標準,通過寄存器傳遞的)。 但對于X86處理器的<a

90、sm/linkage.h>中是這樣定義的:#define asmlinkage CPP_ASMLINKAGE _attribute_(regparm(0)表示函數(shù)的參數(shù)傳遞是通過堆棧完成的。3.7 描述3.3節(jié)中的ret_to_user 中斷返回過程,/arch/arm/kernel/entry-common.SENTRY(ret_to_user)        ret_slow_syscall:         

91、60;    disable_irq disable interrupts              ldr r1, tsk, #TI_FLAGS              tst r1, #_TIF_WORK_MASK     

92、         bne work_pending        no_work_pending:              /* perform architecture specific actions before user return */   &#

93、160;          arch_ret_to_user r1, lr       slow_restore_user_regs              ldr r1, sp, #S_PSR get calling cpsr      

94、;        ldr lr, sp, #S_PC! get pc              msr spsr_cxsf, r1 save in spsr_svc              ldmdb sp, r0 - lr get ca

95、lling r0 - lr              mov r0, r0              add sp, sp, #S_FRAME_SIZE - S_PC             

96、; movs pc, lr return & move spsr_svc into cpsr第三章主要跟蹤了從中斷發(fā)生到調(diào)用到對應(yīng)中斷號的desc->handle_irq(irq, desc)中斷函數(shù)的過程。后面的章節(jié)還會繼續(xù)講解后面的內(nèi)容。四、中斷處理模型 要想弄清楚desc->handle_irq(irq, desc)和我們注冊的中斷有什么關(guān)聯(lián),就要了解中斷處理模型了。 4.1 中斷處理模型結(jié)構(gòu) 中斷處理模型如下圖所示,其中NR_IRQS表示最大的中斷號,在include/asm/arch/irq.h中定義。 irq_desc是一個指向irq_desc_t結(jié)構(gòu)

97、的數(shù)組, irq_desc_t結(jié)構(gòu)是各個設(shè)備中斷服務(wù)例程的描述符。Irq_desc_t結(jié)構(gòu)體中的成員action指向該中斷號對應(yīng)的irqaction結(jié)構(gòu)體 鏈表。Irqaction結(jié)構(gòu)體定義在include/linux/interrupt.h中,如下:truct irqaction         irq_handler_t handler; /中斷處理函數(shù),注冊時提供        unsigned long flags; /中斷標志

98、,注冊時提供        cpumask_t mask; /中斷掩碼        const char *name; /中斷名稱        void *dev_id; /設(shè)備id,本文后面部分介紹中斷共享時會詳細說明這個參數(shù)的作用        struct irqact

99、ion *next; /如果有中斷共享,則繼續(xù)執(zhí)行,        int irq; /中斷號,注冊時提供        struct proc_dir_entry *dir; /指向IRQn相關(guān)的/proc/irq/n目錄的描述符    在注冊中斷號為irq的中斷服務(wù)程序時,系統(tǒng)會根據(jù)注冊參數(shù)封裝相應(yīng)的irqaction結(jié)構(gòu)體。并把中 斷號為irq的irqaction結(jié)構(gòu)體寫入irq_desc

100、irq->action。這樣就把設(shè)備的中斷請求號與該設(shè)備的中斷服務(wù)例程irqaction聯(lián)系在一起了。樣當CPU接收到中斷請求后,就可 以根據(jù)中斷號通過irq_desc 找到該設(shè)備的中斷服務(wù)程序。 4.2 中斷共享的處理模型共享中斷的不同設(shè)備的iqraction結(jié)構(gòu)體都會添加進該中斷號對應(yīng)的irq_desc結(jié)構(gòu)體的 action成員所指向的irqaction鏈表內(nèi)。當內(nèi)核發(fā)生中斷時,它會依次調(diào)用該鏈表內(nèi)所有的handler函數(shù)。因此,若驅(qū)動程序需要使用共享中 斷機制,其中斷處理函數(shù)必須有能力識別是否是自己的硬件產(chǎn)生了中斷。通常是通過讀取該硬件設(shè)備提供的中斷flag標志位進行判斷。也就是說

101、不是任何設(shè)備都 可以做為中斷共享源的,它必須能夠通過的它的中斷flag判斷出是否發(fā)生了中斷。中斷共享的注冊方法是:int request_irq(unsigned int irq, irq_handler_t handler,        IRQF_SHARED, const char *devname, void *dev_id) 很多權(quán)威資料中都提到,中斷共享注冊時的注冊函數(shù)中的dev_id參數(shù)是必不可少的,并且dev_id的值必須唯一。那么這里提供唯一的dev_id值的究竟是做什么用的? 根據(jù)我們前面中斷模

102、型的知識,可以看出發(fā)生中斷時,內(nèi)核并不判斷究竟是共享中斷線上的哪個設(shè)備產(chǎn)生了中斷,它會循環(huán) 執(zhí)行所有該中斷線上注冊的中斷處理函數(shù)(即irqaction->handler函數(shù))。因此irqaction->handler函數(shù)有責 任識別出是否是自己的硬件設(shè)備產(chǎn)生了中斷,然后再執(zhí)行該中斷處理函數(shù)。通常是通過讀取該硬件設(shè)備提供的中斷flag標志位進行判斷。那既然kernel循 環(huán)執(zhí)行該中斷線上注冊的所有irqaction->handler函數(shù),把識別究竟是哪個硬件設(shè)備產(chǎn)生了中斷這件事交給中斷處理函數(shù)本身去做,那 request_irq的dev_id參數(shù)究竟是做什么用的? 很多資料中都

103、建議將設(shè)備結(jié)構(gòu)指針作為dev_id參數(shù)。在中斷到來時,迅速地根據(jù)硬件寄存器中的信息比照傳入的 dev_id參數(shù)判斷是否是本設(shè)備的中斷,若不是,應(yīng)迅速返回。這樣的說法沒有問題,也是我們編程時都遵循的方法。但事實上并不能夠說明為什么中斷共享必 須要設(shè)置dev_id。 下面解釋一下dev_id參數(shù)為什么必須的,而且是必須唯一的。 當調(diào)用free_irq注銷中斷處理函數(shù)時(通常卸載驅(qū)動時其中斷處理函數(shù)也會被注銷掉),因為dev_id是唯一 的,所以可以通過它來判斷從共享中斷線上的多個中斷處理程序中刪除指定的一個。如果沒有這個參數(shù),那么kernel不可能知道給定的中斷線上到底要刪除哪 一個處理程序。注銷

104、函數(shù)定義在Kernel/irq/manage.c中定義:     void free_irq(unsigned int irq, void *dev_id)五、S3C2410子中斷的注冊的實現(xiàn) 5.1 S3C2410子中斷注冊問題的提出參看3.5節(jié)中判斷中斷號的方法,可以看到只是通過S3C2410中斷控制器中的INTOFFSET寄存器來判斷的。對于INTPND中的EINT4_7、EINT8_23、INT_UART0、INT_ADC 等帶有子中斷的向量,INTOFFSET無法判斷出具體的中斷號。平臺留給我們的注冊方法如下: 在include/asm/arc

105、h/irqs.h中有類似如下定義:/* interrupts generated from the external interrupts sources */    #define IRQ_EINT4 S3C2410_IRQ(32) /* 48 */    #define IRQ_EINT5 S3C2410_IRQ(33)    #define IRQ_EINT6 S3C2410_IRQ(34)    #define IRQ_EINT7 S3C2410

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論