在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

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

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

            作者: 時間:2012-09-01 來源:網(wǎng)絡(luò) 收藏

            三、中斷處理過程

            這一節(jié)將以S3C2410為例,描述-2.6.26中,從中斷開始,中斷是如何一步一步執(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模式做準(zhǔn)備

            @

            @ 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 @ 當(dāng)指令的目標(biāo)寄存器是PC,且指令以S結(jié)束,則它會把@ spsr的值恢復(fù)給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作為下一步跟蹤的目標(biāo)。

            3.3 __irq_usr的實現(xiàn) archarmkernelentry-armv.S

            __irq_usr:

            usr_entry @后面有解釋

            kuser_cmpxchg_check

            #ifdef CONFIG_TRACE_IRQFLAGS

            bl trace_hardirqs_off

            #endif

            get_thread_info tsk @獲取當(dāng)前進程的進程描述符中的成員變量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é)有實現(xiàn)過程。

            #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é)有實現(xiàn)過程

            上面代碼中的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不再難懂)


            關(guān)鍵詞: linux 內(nèi)核 ARM中斷

            評論


            相關(guān)推薦

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

            關(guān)閉