ARM Linux中斷源碼分析2——中斷處理流程.docx

上傳人:小** 文檔編號:16821256 上傳時間:2020-10-29 格式:DOCX 頁數(shù):23 大?。?06.48KB
收藏 版權(quán)申訴 舉報 下載
ARM Linux中斷源碼分析2——中斷處理流程.docx_第1頁
第1頁 / 共23頁
ARM Linux中斷源碼分析2——中斷處理流程.docx_第2頁
第2頁 / 共23頁
ARM Linux中斷源碼分析2——中斷處理流程.docx_第3頁
第3頁 / 共23頁

下載文檔到電腦,查找使用更方便

0 積分

下載資源

還剩頁未讀,繼續(xù)閱讀

資源描述:

《ARM Linux中斷源碼分析2——中斷處理流程.docx》由會員分享,可在線閱讀,更多相關(guān)《ARM Linux中斷源碼分析2——中斷處理流程.docx(23頁珍藏版)》請在裝配圖網(wǎng)上搜索。

1、ARM Linux中斷源碼分析(2)中斷處理流程ARM支持7類異常中斷,所以中斷向量表設8個條目,每個條目4字節(jié),共32字節(jié)。異常名稱中斷向量異常中斷模式優(yōu)先級復位0x0特權(quán)模式1未定義的指令0x4未定義指令中止模式6軟件中斷0x8特權(quán)模式6指令預取中止0x0c中止模式5數(shù)據(jù)訪問中止0x10中止模式2保留0x14外部中斷請求IRQ0x18IRQ模式4快速中斷請求FIQ0x1cFIQ模式3回顧第一節(jié)所講的內(nèi)容,當一個異?;蛑袛喟l(fā)生時,處理器會將PC設置為特定地址,從而跳轉(zhuǎn)到已經(jīng)初始化好的異常向量表。因此,要理清中斷處理流程,先從異常向量表開始。對于ARM Linux而言,異常向量表和異常處理程序

2、都存在arch/arm/kernel/entry_armv.S匯編文件中。vector異常向量表點擊(此處)折疊或打開1. .globl_vectors_start2. _vectors_start:3. swiSYS_ERROR04. bvector_und+stubs_offset5. ldrpc,.LCvswi+stubs_offset6. bvector_pabt+stubs_offset7. bvector_dabt+stubs_offset8. bvector_addrexcptn+stubs_offset9. bvector_irq+stubs_offset 中斷入口,vecto

3、r_irq10. bvector_fiq+stubs_offset11.12. .globl_vectors_end13. _vectors_end:vector_irq+stubs_offset為中斷的入口點,此處之所以要加上stubs_offset,是為了實現(xiàn)位置無關(guān)編程。首先分析一下stubs_offset(宏)是如何計算的:.equstubs_offset, _vectors_start + 0x200 - _stubs_start在第3節(jié)中已經(jīng)提到,內(nèi)核啟動時會將異常向量表拷貝到 0xFFFF_0000,將異常向量處理程序的 stub 拷貝到 0xFFFF_0200。圖5-1描述了異

4、常向量表和異常處理程序搬移前后的內(nèi)存布局。圖5-1異常向量表和異常處理程序搬移前后對比當匯編器看到B指令后會把要跳轉(zhuǎn)的標簽轉(zhuǎn)化為相對于當前PC的偏移量(32M)寫入指令碼。由于內(nèi)核啟動時中斷向量表和stubs都發(fā)生了代碼搬移,所以如果中斷向量表中仍然寫成b vector_irq,那么實際執(zhí)行的時候就無法跳轉(zhuǎn)到搬移后的vector_irq處,因為指令碼里寫的是原來的偏移量,所以需要把指令碼中的偏移量寫成搬移后的。設搬移后的偏移量為offset,如圖5-1所示,offset = L1+L2= 0x200 - (irq_PC_X - _vectors_start_X) + (vector_irq_X

5、 - _stubs_start_X)= 0x200 - (irq_PC - _vectors_start) + (vector_irq - _stubs_start)= 0x200 - irq_PC + _vectors_start + vector_irq - _stubs_start= vector_irq + (_vectors_start + 0x200 - _stubs_start) - irq_PC令stubs_offset = _vectors_start + 0x200 - _stubs_start則offset = vector_irq + stubs_offset - ir

6、q_PC,所以中斷入口點為“bvector_irq + stubs_offset”,其中減去irq_PC是由匯編器在編譯時完成的。vector_irq處理函數(shù)在分析vector_irq處理函數(shù)之前,先了解一下當一個異常或中斷導致處理器模式改變時,ARM處理器內(nèi)核的處理流程如下圖所示: 中斷剛發(fā)生時,處理器處于irq模式。在_stubs_start和_stubs_end之間找到vector_irq處理函數(shù)的定義vector_stub irq, IRQ_MODE, 4,其中vector_stub是一個宏(在arch/arm/kernel/entry_armv.S中定義),為了分析更直觀,我們將ve

7、ctor_stub宏展開如下:1. /*2. *Interrupt dispatcher3. */4. vector_irq:5. .if46. sublr,lr,#4在中斷發(fā)生時,lr指向最后執(zhí)行的指令地址加上8。只有在當前指令執(zhí)行完畢后,才進入中斷處理,所以返回地址應指向下一條指令,即(lr-4)處。7. .endif8.9. 10. Save r0,lr_(parent PC)andspsr_11. (parent CPSR)12. 13. stmiasp,r0,lr 保存r0,lr到irq模式下的棧中14. mrslr,spsr15. strlr,sp,#8保存spsr到irq模式下的

8、棧中16.17. 18. PrepareforSVC32 mode.IRQs remain disabled.19. 20. mrsr0,cpsr21. eorr0,r0,#(IRQ_MODE SVC_MODE)設置成SVC模式,但未切換22. msrspsr_cxsf,r0 保存到spsr_irq中23.24. 25. the branch table must immediately followthiscode26. 27. andlr,lr,#0x0f lr存儲著上一個處理器模式的cpsr值,lr=lr & 0x0f取出用于判斷發(fā)生中斷前是用戶態(tài)還是核心態(tài)的信息,該值用于下面跳轉(zhuǎn)表的索

9、引。28. movr0,sp 將irq模式下的sp保存到r0,作為參數(shù)傳遞給即將調(diào)用的_irq_usr或_irq_svc29. ldrlr,pc,lr,lsl#2pc指向當前執(zhí)行指令地址加8,即跳轉(zhuǎn)表的基址。lr作為索引,由于是4字節(jié)對齊,所以lr=lr2.30. movspc,lr branch to handlerinSVC mode31. 當mov指令后加“s”且目標寄存器為pc時,當前模式下的spsr會被復制到cpsr,從而完成模式切換(從irq模式切換到svc模式)并且跳轉(zhuǎn)到pc指向的指令繼續(xù)執(zhí)行32. ENDPROC(vector_irq)33.34. .long_irq_usr

10、0(USR_26 / USR_32)35. .long_irq_invalid 1(FIQ_26 / FIQ_32)36. .long_irq_invalid 2(IRQ_26 / IRQ_32)37. .long_irq_svc 3(SVC_26 / SVC_32)38. .long_irq_invalid 439. .long_irq_invalid 540. .long_irq_invalid 641. .long_irq_invalid 742. .long_irq_invalid 843. .long_irq_invalid 944. .long_irq_invalid a45. .

11、long_irq_invalid b46. .long_irq_invalid c47. .long_irq_invalid d48. .long_irq_invalid e49. .long_irq_invalid f_irq_usr如果發(fā)生中斷前處于用戶態(tài)則進入_irq_usr,其定義如下(arch/arm/kernel/entry_armv.S):1. .align52. _irq_usr:3. usr_entry 保存中斷上下文,稍后分析4. kuser_cmpxchg_check5. #ifdef CONFIG_TRACE_IRQFLAGS6. bltrace_hardirqs_of

12、f7. #endif8. get_thread_info tsk 獲取當前進程的進程描述符中的成員變量thread_info的地址,并將該地址保存到寄存器tsk(r9)(在entry-header.S中定義)9. #ifdef CONFIG_PREEMPT 如果定義了搶占,增加搶占數(shù)值10. ldrr8,tsk,#TI_PREEMPT 獲取preempt計數(shù)器值11. addr7,r8,#1 preempt加1,標識禁止搶占12. strr7,tsk,#TI_PREEMPT將加1后的結(jié)果寫入進程內(nèi)核棧的變量中13. #endif14. irq_handler 調(diào)用中斷處理程序,稍后分析15.

13、#ifdef CONFIG_PREEMPT16. ldrr0,tsk,#TI_PREEMPT獲取preempt計數(shù)器值17. strr8,tsk,#TI_PREEMPT將preempt恢復到中斷前的值18. teqr0,r7 比較中斷前后preempt是否相等19. strner0,r0,-r0如果不等,則產(chǎn)生異常(向地址0寫入數(shù)據(jù))?20. #endif21. #ifdef CONFIG_TRACE_IRQFLAGS22. bltrace_hardirqs_on23. #endif24. movwhy,#0 r8=025. bret_to_user 中斷處理完成,恢復中斷上下文并返回中斷產(chǎn)生

14、的位置,稍后分析26. UNWIND(.fnend)27. ENDPROC(_irq_usr)宏定義usr_entry(保護上下文到棧)上面代碼中的usr_entry是一個宏定義,主要用于保護上下文到棧中:1. .macrousr_entry2. UNWIND(.fnstart)3. UNWIND(.cantunwind) dont unwind the user space4. subsp,sp,#S_FRAME_SIZE ATPCS中,堆棧被定義為遞減式滿堆棧,所以首先讓sp向下移動#S_FRAME_SIZE(pt_regs結(jié)構(gòu)體size),準備向棧中存放數(shù)據(jù)。此處的sp是svc模式下的棧

15、指針。5. stmibsp,r1-r126.7. ldmiar0,r1-r38. addr0,sp,#S_PC hereforinterlock avoidance9. movr4,#-110.11. strr1,sp save therealr0 copied12. from the exception stack13.14. 15. We are now ready to fillinthe remaining blanks on the stack:16. 17. r2-lr_,already fixed upforcorrect return/restart18. r3-spsr_19

16、. r4-orig_r0(see pt_regs definitioninptrace.h)20. 21. Also,separately save sp_usrandlr_usr22. 23. stmiar0,r2-r424. stmdbr0,sp,lr 將user模式下的sp和lr保存到svc模式的棧中25.26. 27. Enable the alignment trapwhileinkernel mode28. 29. alignment_trap r030.31. 32. Clear FP to mark the first stack frame33. 34. zero_fp35.

17、 .endm上面的這段代碼主要是在填充結(jié)構(gòu)體pt_regs ,在include/asm/ptrace.h中定義:1. structpt_regs 2. long uregs18;3. ;4.5. #define ARM_cpsruregs166. #define ARM_pcuregs157. #define ARM_lruregs148. #define ARM_spuregs139. #define ARM_ipuregs1210. #define ARM_fpuregs1111. #define ARM_r10uregs1012. #define ARM_r9uregs913. #def

18、ine ARM_r8uregs814. #define ARM_r7uregs715. #define ARM_r6uregs616. #define ARM_r5uregs517. #define ARM_r4uregs418. #define ARM_r3uregs319. #define ARM_r2uregs220. #define ARM_r1uregs121. #define ARM_r0uregs022. #define ARM_ORIG_r0uregs17usr_entry宏填充pt_regs結(jié)構(gòu)體的過程如圖5-2所示,先將r1r12保存到ARM_r1ARM_ip(綠色部分),

19、然后將產(chǎn)生中斷時的r0寄存器內(nèi)容保存到ARM_r0(藍色部分),接下來將產(chǎn)生中斷時的下一條指令地址lr_irq、spsr_irq和r4保存到ARM_pc、ARM_cpsr和ARM_ORIG_r0(紅色部分),最后將用戶模式下的sp和lr保存到ARM_sp和ARM_lr中。圖5-2 usr_entry宏填充pt_regs結(jié)構(gòu)體_irq_svc如果發(fā)生中斷前處于核心態(tài)則進入_irq_svc,其定義如下(arch/arm/kernel/entry_armv.S):1. .align52. _irq_svc:3. svc_entry 保存中斷上下文4.5. #ifdef CONFIG_TRACE_IR

20、QFLAGS6. bltrace_hardirqs_off7. #endif8. #ifdef CONFIG_PREEMPT9. get_thread_info tsk10. ldrr8,tsk,#TI_PREEMPT 獲取preempt計數(shù)器值11. addr7,r8,#1 preempt加1,標識禁止搶占12. strr7,tsk,#TI_PREEMPT將加1后的結(jié)果寫入進程內(nèi)核棧的變量中13. #endif14.15. irq_handler 調(diào)用中斷處理程序,稍后分析16. #ifdef CONFIG_PREEMPT17. strr8,tsk,#TI_PREEMPT 恢復中斷前的pre

21、empt計數(shù)器18. ldrr0,tsk,#TI_FLAGS 獲取flags19. teqr8,#0 判斷preempt是否等于020. movner0,#0 如果preempt不等于0,r0=021. tstr0,#_TIF_NEED_RESCHED 將r0與#_TIF_NEED_RESCHED做“與操作”22. blnesvc_preempt 如果不等于0,說明發(fā)生內(nèi)核搶占,需要重新調(diào)度。23. #endif24.25. ldrr0,sp,#S_PSR irqs are already disabled26. msrspsr_cxsf,r027. #ifdef CONFIG_TRACE_I

22、RQFLAGS28. tstr0,#PSR_I_BIT29. bleqtrace_hardirqs_on30. #endif31. svc_exit r4 恢復中斷上下文,稍后分析。32. UNWIND(.fnend)33. ENDPROC(_irq_svc)宏定義svc_entry(保護中斷上下文到棧)其中svc_entry是一個宏定義,主要用于保護中斷上下文到棧中。svc_entry主要是在當前堆棧上分配一個pt_regs結(jié)構(gòu),把r0-r15以及cpsr等保存到這個結(jié)構(gòu)中,在進入irq_handler時,sp指向pt_regs底端:1. .macrosvc_entry,stack_hole

23、=02. UNWIND(.fnstart)3. UNWIND(.save r0-pc)4. subsp,sp,#(S_FRAME_SIZE+stack_hole)5. SPFIX(tstsp,#4)6. SPFIX(bicnesp,sp,#4)7. stmibsp,r1-r128.9. ldmiar0,r1-r310. addr5,sp,#S_SP hereforinterlock avoidance11. movr4,#-112. addr0,sp,#(S_FRAME_SIZE+stack_hole)13. SPFIX(addner0,r0,#4)14. strr1,sp save ther

24、ealr0 copied15. from the exception stack16.17. movr1,lr18.19. 20. We are now ready to fillinthe remaining blanks on the stack:21. 22. r0-sp_svc23. r1-lr_svc24. r2-lr_,already fixed upforcorrect return/restart25. r3-spsr_26. r4-orig_r0(see pt_regs definitioninptrace.h)27. 28. stmiar5,r0-r429. .endmsv

25、c_entry宏填充pt_regs結(jié)構(gòu)體的過程如圖5-2所示,先將r1r12保存到ARM_r1ARM_ip(綠色部分),然后將產(chǎn)生中斷時的r0寄存器內(nèi)容保存到ARM_r0(藍色部分),由于是在svc模式下產(chǎn)生的中斷,所以最后將sp_svc、lr_svc、lr_irq、spsr_irq和r4保存到ARM_sp、ARM_lr、ARM_pc、ARM_cpsr和ARM_ORIG_r0(紅色部分)。圖5-3 svc_entry宏填充pt_regs結(jié)構(gòu)體上述的中斷上下文保存過程共涉及了3種棧指針,分別是:用戶空間棧指針sp_usr,內(nèi)核空間棧指針sp_svc和irq模式下的棧棧指針sp_irq。sp_us

26、r指向在setup_arg_pages函數(shù)中創(chuàng)建的用戶空間棧。sp_svc指向在alloc_thread_info函數(shù)中創(chuàng)建的內(nèi)核空間棧。sp_irq在cpu_init函數(shù)中被賦值,指向全局變量stacks.irq0。附錄1,arm體系下pt_regs結(jié)構(gòu)structpt_regs long uregs18;uregs0 - uregs17分別對應,r0 - r15,cpsr,ORIG_r0附錄1,irq中斷時堆棧的變化-spsr-lr ,中斷返回地址,修正后的-r0- -進入irq_svc之前,sp的值,也是r0的值pt_regs- flags6. tstr1,#_TIF_WORK_MASK

27、 判斷是否有待處理的work7. bnework_pending 如果有,則進入work_pending進一步處理,主要是完成用戶進程搶占相關(guān)處理。8. no_work_pending:如果沒有work待處理,則準備恢復中斷現(xiàn)場,返回用戶空間。9. /*perform architecture specific actions before user return*/10. arch_ret_to_user r1,lr 調(diào)用體系結(jié)構(gòu)相關(guān)的代碼11.12. restore_user_regs fast=0,offset=0 調(diào)用restore_user_regs13. ENDPROC(ret_t

28、o_user)14.15. 以下是恢復中斷現(xiàn)場寄存器的宏,就是將發(fā)生中斷時保存在內(nèi)核空間堆棧上的寄存器還原,可以對照圖5-2所示的內(nèi)核空間堆棧保存的內(nèi)容來理解下面代碼:16. .macrorestore_user_regs,fast=0,offset=017. ldrr1,sp,#offset+S_PSR 從內(nèi)核棧中獲取發(fā)生中斷時的cpsr值18. ldrlr,sp,#offset+S_PC! 從內(nèi)核棧中獲取發(fā)生中斷時的下一條指令地址19. msrspsr_cxsf,r1 將r1保存到spsr_svc20. #ifdefined(CONFIG_CPU_32v6K)21. clrex clear

29、 the exclusive monitor22. #elif defined(CONFIG_CPU_V6)23. strexr1,r2,sp clear the exclusive monitor24. #endif25. .iffast26. ldmdbsp,r1-lr get calling r1-lr27. .else28. ldmdbsp,r0-lr 存在,所以將內(nèi)核棧保存的內(nèi)容恢復到用戶空間的r0lr寄存器29. .endif30. addsp,sp,#S_FRAME_SIZE-S_PC31. movspc,lr將發(fā)生中斷時的下一條指令地址存入pc,從而返回中斷點繼續(xù)執(zhí)行,并且將發(fā)

30、生中斷時的cpsr內(nèi)容恢復到cpsr寄存器中(開啟中斷)。32. .endmsvc_exit如果中斷產(chǎn)生于內(nèi)核空間,則調(diào)用svc_exit來恢復中斷現(xiàn)場:1. arch/arm/kernel/ entry-header.S2. .macrosvc_exit,rpsr3. msrspsr_cxsf,rpsr4. #ifdefined(CONFIG_CPU_32v6K)5. clrex clear the exclusive monitor6. ldmiasp,r0-pc load r0-pc,cpsr7. #elif defined(CONFIG_CPU_V6)8. ldrr0,sp9. str

31、exr1,r2,sp clear the exclusive monitor10. ldmibsp,r1-pc load r1-pc,cpsr11. #else12. ldmiasp,r0-pc 返回內(nèi)核空間時,恢復中斷現(xiàn)場比較簡單,就是將r0-pc以及cpsr恢復即可,同時中斷也被開啟。13. #endif14. .endmasm_do_IRQ函數(shù)ok,分析完所有與中斷相關(guān)的匯編語言代碼后,下面開始分析C語言代碼:在arch/arm/kernel/irq.c文件中找到asm_do_IRQ函數(shù)定義:1. asmlinkage void _exception asm_do_IRQ(unsigne

32、dintirq,structpt_regs*regs)2. 3. /*保存新的寄存器集合指針到全局cpu變量,方便后續(xù)處理程序訪問寄存器集合。*/4. structpt_regs*old_regs=set_irq_regs(regs);5.6. irq_enter();7.8. /*9. *Some hardware gives randomly wrong interrupts.Rather10. *than crashing,do something sensible.11. */12. if(unlikely(irq=NR_IRQS) /判斷中斷號13. if(printk_rateli

33、mit()14. printk(KERN_WARNINGBad IRQ%un,irq);15. ack_bad_irq(irq);16. else17. generic_handle_irq(irq);/調(diào)用中斷處理函數(shù)18. 19.20. /*AT91 specific workaround*/21. irq_finish(irq);22.23. irq_exit();24. set_irq_regs(old_regs);25. asm_do_IRQ是中斷處理的C入口函數(shù),主要負責調(diào)用request_irq注冊的中斷處理函數(shù),其流程如圖5-4所示:圖5-4 asm_do_IRQ流程1、old

34、_regs=set_irq_regs(regs)其中,set_irq_regs將指向寄存器結(jié)構(gòu)體的指針保存在一個全局的CPU變量中,后續(xù)的程序可以通過該變量訪問寄存器結(jié)構(gòu)體。所以在進入中斷處理前,先將全局CPU變量中保存的舊指針保留下來,等到中斷處理結(jié)束后再將其恢復。2、irq_enterirq_enter負責更新一些統(tǒng)計量:1. 2. void irq_enter(void)3. 4. intcpu=smp_processor_id();5.6. rcu_irq_enter();7. if(idle_cpu(cpu)&!in_interrupt()8. _irq_enter();9. tic

35、k_check_idle(cpu);10. else11. _irq_enter();12. 如果系統(tǒng)開啟動態(tài)時鐘特性且很長時間沒有產(chǎn)生時鐘中斷,則調(diào)用tick_check_idle更新全局變量jiffies(關(guān)于動態(tài)時鐘特性,在后續(xù)的總結(jié)中再進行分析)。宏_irq_enter()定義如下:1. #define _irq_enter()2. do3. account_system_vtime(current);4. add_preempt_count(HARDIRQ_OFFSET);5. trace_hardirq_enter();6. while(0)add_preempt_count(HA

36、RDIRQ_OFFSET)使表示中斷處理程序嵌套層次的計數(shù)器加1。計數(shù)器保存在當前進程thread_info結(jié)構(gòu)的preempt_count字段中:圖5-5 preempt_count結(jié)構(gòu)內(nèi)核將preempt_count分成5部分:bit07與PREEMPT相關(guān),bit815用作軟中斷計數(shù)器,bit1625用作硬中斷計數(shù)器,bit26用作不可屏蔽中斷計數(shù)器,bit28用作PREEMPT_ACTIVE標志。3、generic_handle_irqgeneric_handle_irq是體系結(jié)構(gòu)無關(guān)函數(shù),用來調(diào)用desc-handle_irq,該函數(shù)指針在中斷初始化時指向了電流處理函數(shù)(handle

37、_level_irq或handle_edge_irq),針對不同的中斷觸發(fā)類型(邊沿觸發(fā)或電平觸發(fā))做相應的處理。然后調(diào)用handle_IRQ_event遍歷action鏈表從而調(diào)用該中斷號對應的一個或多個中斷處理程序action-handler,而action-handler就是通過request_irq初始化的。handle_level_irq首先分析一下handle_level_irq函數(shù):1. 2. void handle_level_irq(unsignedintirq,struct irq_desc*desc)3. 4. struct irqaction*action;5. irq

38、return_t action_ret;6.7. spin_lock(&desc-lock);/*訪問desc內(nèi)容之前先加自旋鎖*/8. mask_ack_irq(desc,irq);/*屏蔽與irq號對應的中斷線*/9.10. /*在多處理器系統(tǒng)上,為了避免多cpu同時處理同一中斷。11. *當desc-status包含IRQ_INPROGRESS標志時,說明該中斷12. *正在另一個cpu上處理,因此當前cpu可以直接放棄處理。13. */14. if(unlikely(desc-status&IRQ_INPROGRESS)15. goto out_unlock;16. desc-stat

39、us&=(IRQ_REPLAY|IRQ_WAITING);17. kstat_incr_irqs_this_cpu(irq,desc);18.19. /*20. *如果沒有對該中斷注冊處理程序,即desc-action為NULL。21. *或者desc-status設置為IRQ_DISABLED,表示該中斷是被禁止的。22. *以上兩種情況只要出現(xiàn)一種即可放棄處理。23. */24. action=desc-action;25. if(unlikely(!action|(desc-status&IRQ_DISABLED)26. goto out_unlock;27.28. desc-statu

40、s|=IRQ_INPROGRESS;/*標識中斷狀態(tài)為正在處理*/29. spin_unlock(&desc-lock);/*釋放自旋鎖*/30.31. /*調(diào)用由request_irq注冊的處理函數(shù),稍后分析。*/32. action_ret=handle_IRQ_event(irq,action);33. if(!noirqdebug)34. note_interrupt(irq,desc,action_ret);35.36. spin_lock(&desc-lock);/*訪問desc內(nèi)容前加自旋鎖*/37. desc-status&=IRQ_INPROGRESS;/*清除“正在處理”的

41、標識*/38.39. /*如果desc-status 包含IRQ_ONESHOT,40. *則將desc-status設置為IRQ_MASKED,使該中斷仍處于被屏蔽狀態(tài)。*/41. if(unlikely(desc-status&IRQ_ONESHOT)42. desc-status|=IRQ_MASKED;43. /*如果中斷處理函數(shù)中未對desc-status 設置為IRQ_ DISABLED,44. *且desc-chip-unmask不為空,則desc-chip-unmask所指向的芯片相關(guān)函數(shù),45. *解除對該中斷的屏蔽。46. */47. elseif(!(desc-statu

42、s&IRQ_DISABLED)&desc-chip-unmask)48. desc-chip-unmask(irq);49. out_unlock:50. spin_unlock(&desc-lock);/*釋放自旋鎖*/51. handle_edge_irq再來介紹一下handle_edge_irq函數(shù),相對于handle_level_irq要復雜一點:1. 2. void handle_edge_irq(unsignedintirq,struct irq_desc*desc)3. 4. spin_lock(&desc-lock);5. desc-status&=(IRQ_REPLAY|IR

43、Q_WAITING);6. /*7. *如果該中斷正在被其他cpu處理,或者是該中斷已被禁止,8. *則不處理該中斷,但要將其標識為pending狀態(tài)且屏蔽該中斷以便后續(xù)處理9. */10. if(unlikely(desc-status&(IRQ_INPROGRESS|IRQ_DISABLED)|11. !desc-action)12. desc-status|=(IRQ_PENDING|IRQ_MASKED);13. mask_ack_irq(desc,irq);14. goto out_unlock;15. 16. kstat_incr_irqs_this_cpu(irq,desc);1

44、7.18. /*Start handling the irq*/19. if(desc-chip-ack)20. desc-chip-ack(irq);21.22. /*標識該中斷狀態(tài)為“正在處理”*/23. desc-status|=IRQ_INPROGRESS;24.25. do26. struct irqaction*action=desc-action;27. irqreturn_t action_ret;28.29. if(unlikely(!action)30. desc-chip-mask(irq);31. goto out_unlock;32. 33.34. /*35. *如果

45、當處理該中斷時有另一個中斷到達,36. *那么當時可能屏蔽了該中斷。37. *如果該中斷沒有被禁止,則解除對該中斷的屏蔽。38. */39. if(unlikely(desc-status&40. (IRQ_PENDING|IRQ_MASKED|IRQ_DISABLED)=41. (IRQ_PENDING|IRQ_MASKED)42. desc-chip-unmask(irq);43. desc-status&=IRQ_MASKED;44. 45.46. desc-status&=IRQ_PENDING;47. spin_unlock(&desc-lock);48. /*調(diào)用由request_

46、irq注冊的處理函數(shù),稍后分析。*/49. action_ret=handle_IRQ_event(irq,action);50. if(!noirqdebug)51. note_interrupt(irq,desc,action_ret);52. spin_lock(&desc-lock);53. /*如果該中斷沒有被禁止,并且有其他中斷等待處理(IRQ_PENDING),54. *則循環(huán)處理其他中斷。55. */56. while(desc-status&(IRQ_PENDING|IRQ_DISABLED)=IRQ_PENDING);57.58. desc-status&=IRQ_INPROGRESS;59. out_unlock:60. spin_unlock(&desc-lock);61. handle_IRQ_event不管是電平觸發(fā)還是邊沿觸發(fā),最終都會通過handle_IRQ_event來調(diào)用注冊的中斷處理函數(shù)。1. 2. irqreturn_t handle_IRQ_event(unsignedintirq,struct irqaction*action)3. 4. irqreturn_t ret,retval=IRQ_NONE;5. unsignedintstatus=0;6.7. /*如果注冊中

展開閱讀全文
溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

相關(guān)資源

更多
正為您匹配相似的精品文檔
關(guān)于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號:ICP2024067431-1 川公網(wǎng)安備51140202000466號


本站為文檔C2C交易模式,即用戶上傳的文檔直接被用戶下載,本站只是中間服務平臺,本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請立即通知裝配圖網(wǎng),我們立即給予刪除!