<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > linux-2.6.26內(nèi)核中ARM中斷實現(xiàn)詳解(2)

          linux-2.6.26內(nèi)核中ARM中斷實現(xiàn)詳解(2)

          作者: 時間:2012-08-21 來源:網(wǎng)絡 收藏

          三、處理過程

          本文引用地址:http://www.ex-cimer.com/article/148559.htm

          這一節(jié)將以S3C2410為例,描述中,從開始,是如何一步一步執(zhí)行到我們注冊函數(shù)的。

          3.1 中斷向量表 archarmkernelentry-armv.S

          __vectors_STart:

          swi SYS_ERROR0

          b vector_und + stubs_offset

          ldr pc, .LCvswi + stubs_offset

          b vector_pa^ + stubs_offset

          b vector_da^ + stubs_offset

          b vector_addrexcptn + stubs_offset

          b vector_IRq + stubs_offset

          b vector_fiq + stubs_offset

          .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 __stubs_start

          __stubs_start:

          /*

          * Interrupt dispatcher

          */

          vector_stub irq, IRQ_MODE, 4 @IRQ_MODE在includeasmptrace.h中定義:0x12

          .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

          .long __irq_invalid @ 5

          .long __irq_invalid @ 6

          .long __irq_invalid @ 7

          .long __irq_invalid @ 8

          .long __irq_invalid @ 9

          .long __irq_invalid @ a

          .long __irq_invalid @ b

          .long __irq_invalid @ c

          .long __irq_invalid @ d

          .long __irq_invalid @ e

          .long __irq_invalid @ f

          上面代碼中vector_stub宏的定義為:

          .macro vector_stub, name, mode, correcTIon=0

          .align 5

          vector_nAME:

          .if correction

          sub lr, lr, #correction

          .endif

          @

          @ Save r0, lr_ (parent PC) and spsr_

          @ (parent CPSR)

          @

          stmia sp, {r0, lr} @ save r0, lr

          mrs lr, spsr

          str lr, [sp, #8] @ save spsr

          @

          @ Prepare for SVC32 mode. IRQs remain disabled.

          @

          mrs r0, cpsr

          eor r0, r0, #(mode ^ SVC_MODE)

          msr spsr_cxsf, r0 @為后面進入svc模式做準備

          @

          @ the branch table must immediately follow this code

          @

          and lr, lr, #0x0f @進入中斷前的mode的后4位

          @#define USR_MODE 0x00000010

          @#define FIQ_MODE 0x00000011

          @#define IRQ_MODE 0x00000012

          @#define SVC_MODE 0x00000013

          @#define ABT_MODE 0x00000017

          @#define UND_MODE 0x0000001b

          @#define SYSTEM_MODE 0x0000001f

          mov r0, sp

          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的值恢復給cpsr branch to handler in SVC mode

          .endm

          .globl __stubs_start

          __stubs_start:

          /*

          * Interrupt dispatcher

          */

          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)

          用“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的 archarmkernelentry-armv.S

          __irq_usr:

          usr_entry @后面有解釋

          kuser_cmpxchg_check

          #ifdef CONFIG_TRACE_IRQFLAGS

          bl trace_hardirqs_off

          #endif

          get_thread_info tsk @獲取當前進程的進程描述符中的成員變量thread_info的地址,并將該地址保存到寄存器tsk等于r9(在entry-header.S中定義)

          #ifdef CONFIG_PREEMPT//如果定義了搶占,增加搶占數(shù)值

          ldr r8, [tsk, #TI_PREEMPT] @ get preempt count

          add r7, r8, #1 @ increment it

          str r7, [tsk, #TI_PREEMPT]

          #endif

          irq_handler @中斷處理,我們最關(guān)心的地方,3.4節(jié)有過程。

          #ifdef CONFIG_PREEMPT

          ldr r0, [tsk, #TI_PREEMPT]

          str r8, [tsk, #TI_PREEMPT]

          teq r0, r7

          strne r0, [r0, -r0]

          #endif

          #ifdef CONFIG_TRACE_IRQFLAGS

          bl trace_hardirqs_on

          #endif

          mov why, #0

          b ret_to_user @中斷處理完成,返回中斷產(chǎn)生的位置,3.7節(jié)有過程

          上面代碼中的usr_entry是一個宏,主要實現(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 - r12}

          ldmia r0, {r1 - r3}

          add r0, sp, #S_PC @ here for interlock avoidance

          mov r4, #-1 @

          str r1, [sp] @ save the real r0 copied

          @ from the exception stack

          @

          @ We are now ready to fill in the remaining blanks on the stack:

          linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

          上一頁 1 2 3 下一頁

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();