• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > linux-2.6.26內核中ARM中斷實現詳解

    linux-2.6.26內核中ARM中斷實現詳解

    作者: 時間:2012-09-01 來源:網絡 收藏

    @

    @ r2 - lr_, already fixed up for correct return/restart

    @ r3 - spsr_

    @ r4 - orig_r0 (see pt_regs definition in ptrace.h)

    @

    @ Also, separately save sp_usr and lr_usr

    @

    stmia r0, {r2 - r4}

    stmdb r0, {sp, lr}^

    @

    @ Enable the alignment trap while in kernel mode

    @

    alignment_trap r0

    @

    @ Clear FP to mark the first stack frame

    @

    zero_fp

    .endm

    上面的這段代碼主要在填充結構體pt_regs ,這里提到的struct pt_regs,在include/asm/ptrace.h中定義。此時sp指向struct pt_regs。

    struct pt_regs {

    long uregs[18];

    };

    #define ARM_cpsr uregs[16]

    #define ARM_pc uregs[15]

    #define ARM_lr uregs[14]

    #define ARM_sp uregs[13]

    #define ARM_ip uregs[12]

    #define ARM_fp uregs[11]

    #define ARM_r10 uregs[10]

    #define ARM_r9 uregs[9]

    #define ARM_r8 uregs[8]

    #define ARM_r7 uregs[7]

    #define ARM_r6 uregs[6]

    #define ARM_r5 uregs[5]

    #define ARM_r4 uregs[4]

    #define ARM_r3 uregs[3]

    #define ARM_r2 uregs[2]

    #define ARM_r1 uregs[1]

    #define ARM_r0 uregs[0]

    #define ARM_ORIG_r0 uregs[17]

    3.4 irq_handler的實現過程,archarmkernelentry-armv.S

    .macro irq_handler

    get_irqnr_preamble r5, lr

    @在include/asm/arch-s3c2410/entry-macro.s中定義了宏get_irqnr_preamble為空操作,什么都不做

    1: get_irqnr_and_base r0, r6, r5, lr @判斷中斷號,通過R0返回,3.5節有實現過程

    movne r1, sp

    @

    @ routine called with r0 = irq number, r1 = struct pt_regs *

    @

    adrne lr, 1b

    bne asm_do_IRQ @進入中斷處理。

    ……

    .endm

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

    @@ try the interrupt offset register, since it is there

    ldr irqstat, [ base, #INTPND ]

    teq irqstat, #0

    beq 1002f

    ldr irqnr, [ base, #INTOFFSET ] @通過判斷INTOFFSET寄存器得到中斷位置

    mov tmp, #1

    tst irqstat, tmp, lsl irqnr

    bne 1001f

    @@ the number specified is not a valid irq, so try

    @@ and work it out for ourselves

    mov irqnr, #0 @@ start here

    @@ work out which irq (if any) we got

    movs tmp, irqstat, lsl#16

    addeq irqnr, irqnr, #16

    moveq irqstat, irqstat, lsr#16

    tst irqstat, #0xff

    addeq irqnr, irqnr, #8

    moveq irqstat, irqstat, lsr#8

    tst irqstat, #0xf

    addeq irqnr, irqnr, #4

    moveq irqstat, irqstat, lsr#4

    tst irqstat, #0x3

    addeq irqnr, irqnr, #2

    moveq irqstat, irqstat, lsr#2

    tst irqstat, #0x1

    addeq irqnr, irqnr, #1

    @@ we have the value

    1001:

    adds irqnr, irqnr, #IRQ_EINT0 @加上中斷號的基準數值,得到最終的中斷號,注意:此時沒有考慮子中斷的具體情況,(子中斷的問題后面會有講解)。IRQ_EINT0在include/asm/arch-s3c2410/irqs.h中定義.從這里可以看出,中斷號的具體值是有平臺相關的代碼決定的,和硬件中斷掛起寄存器中的中斷號是不等的。

    1002:

    @@ exit here, Z flag unset if IRQ

    .endm

    3.6 asm_do_IRQ實現過程,arch/arm/kernel/irq.c

    asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)

    {

    struct pt_regs *old_regs = set_irq_regs(regs);

    struct irq_desc *desc = irq_desc + irq;//根據中斷號找到對應的irq_desc

    /*

    * Some hardware gives randomly wrong interrupts. Rather

    * than crashing, do something sensible.

    */

    if (irq >= NR_IRQS)

    desc = bad_irq_desc;

    irq_enter();//沒做什么特別的工作,可以跳過不看

    desc_handle_irq(irq, desc);// 根據中斷號和desc進入中斷處理

    /* AT91 specific workaround */

    irq_finish(irq);

    irq_exit();

    set_irq_regs(old_regs);

    }

    static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc)

    {

    desc->handle_irq(irq, desc);//中斷處理

    }

    上述asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)使用了asmlinkage標識。那么這個標識的含義如何理解呢?

    該符號定義在kernel/include//linkage.h中,如下所示:

    #include //各個具體處理器在此文件中定義asmlinkage

    #ifdef __cplusplus

    #define CPP_ASMLINKAGE extern "C"

    #else

    #define CPP_ASMLINKAGE

    #endif

    #ifndef asmlinkage//如果以前沒有定義asmlinkage

    #define asmlinkage CPP_ASMLINKAGE

    #endif

    對于ARM處理器的,沒有定義asmlinkage,所以沒有意義(不要以為參數是從堆棧傳遞的,對于ARM平臺來說還是符合ATPCS過程調用標準,通過寄存器傳遞的)。

    但對于X86處理器的中是這樣定義的:

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


    關鍵詞: linux 內核 ARM中斷

    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 信阳市| 兴义市| 高碑店市| 宣城市| 浦东新区| 温泉县| 格尔木市| 额济纳旗| 安阳县| 上林县| 县级市| 山东| 江永县| 韶山市| 柳州市| 建瓯市| 泾阳县| 岑溪市| 巴楚县| 南安市| 綦江县| 巫山县| 惠州市| 桑植县| 莎车县| 大厂| 东乡族自治县| 共和县| 光山县| 双鸭山市| 九江市| 读书| 内乡县| 三原县| 运城市| 合阳县| 皮山县| 宜黄县| 米泉市| 石渠县| 邛崃市|