zoukankan      html  css  js  c++  java
  • 中断服务程序小结

                        ---------------by nasiry 
                                         转载请说明出处,并通知我 

    MACRO
    $HandlerLabel HANDLER $HandleLabel

    $HandlerLabel
     sub sp,sp,#4 ;decrement sp(to store jump address)
     stmfd sp!,{r0} ;PUSH the work register to stack(lr does't push because it return to original address)
     ldr     r0,=$HandleLabel;load the address of HandleXXX to r0
     ldr     r0,[r0]  ;load the contents(service routine start address) of HandleXXX
     str     r0,[sp,#4]      ;store the contents(ISR) of HandleXXX to stack
     ldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)
     MEND


            b ResetHandler     ;0x0
     b HandlerUndef ;handler for Undefined mode
     b HandlerSWI ;handler for SWI interrupt
     b HandlerPabort ;handler for PAbort
     b HandlerDabort ;handler for DAbort
     b .  ;reserved
     b HandlerIRQ ;handler for IRQ interrupt
     b HandlerFIQ ;handler for FIQ interrupt

     LTORG
    HandlerFIQ      HANDLER HandleFIQ
    HandlerIRQ      HANDLER HandleIRQ
    HandlerUndef    HANDLER HandleUndef
    HandlerSWI      HANDLER HandleSWI
    HandlerDabort   HANDLER HandleDabort
    HandlerPabort   HANDLER HandlePabort

    IsrIRQ
     sub sp,sp,#4       ;reserved for PC
     stmfd sp!,{r8-r9}

     ldr r9,=INTOFFSET
     ldr r9,[r9]
     ldr r8,=HandleEINT0
     add r8,r8,r9,lsl #2
     ldr r8,[r8]
     str r8,[sp,#8]
     ldmfd sp!,{r8-r9,pc}

       ; Setup IRQ handler
     ldr r0,=HandleIRQ       ;This routine is needed
     ldr r1,=IsrIRQ   ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c
     str r1,[r0]
    与中断相关的内容展开来看:

    0x1c: b HandlerIRQ

    HandlerIRQ:
      sub sp,sp,#4 ;decrement sp(to store jump address)
     stmfd sp!,{r0} ;PUSH the work register to stack(lr does't push because it return to original address)
     ldr     r0,=HandleIRQ   ;load the address of HandleXXX to r0  //注意是HandleIRQ不是HandlerIRQ
     ldr     r0,[r0]   ;load the contents(service routine start address) of HandleXXX
     str     r0,[sp,#4]      ;store the contents(ISR) of HandleXXX to stack
     ldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)

    IsrIRQ
     sub sp,sp,#4       ;reserved for PC
     stmfd sp!,{r8-r9}

     ldr r9,=INTOFFSET
     ldr r9,[r9]
     ldr r8,=HandleEINT0
     add r8,r8,r9,lsl #2
     ldr r8,[r8]
     str r8,[sp,#8]
     ldmfd sp!,{r8-r9,pc}

       ; Setup IRQ handler
     ldr r0,=HandleIRQ       ;This routine is needed
     ldr r1,=IsrIRQ   ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c
     str r1,[r0]
    看这个具体的例子说明了中断的安装过程其实也就是设置变量HandleIRQ的过程,这样一来有很多好处,使得原本静态安装的中断服务程序具备了动态特性。也同时约束了中断程序所要求的一些特性:1.中断使用前必须初始化。2.初始化的动作必须在使用前完成 3.中断服务程序的初始化仅仅需要挂接相应的函数指针就可以完成。


     

    针对smdk2440的eboot该如何添加中断代码?
    smdk2440的eboot工作在所谓的catfish模式:这个eboot以在RAM中运行为特点,也就说不具备xip的特性,由于我们使用的eboot是从0x0启动的,也就是说我们需要搬运相应的中断向量到影射后的0x0区域,也就是0x30000000区域,代码如下
    BringUpWinCE
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;Modify for ROM Bootloader NASIRY 2004.6.28
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    MoveLoaderToRAM
    ; ands r9, pc, #0xFF000000 ; see if we are in flash or in ram
    ;  bne %F15   ; go ahead if we are already in ram 
      ldr r2,=0x0
      ldr r3,=0x30038000

      ldr r0, [r2], #4
      str r0, [r3], #4
      cmp r2,#0x60000
      bne %b1
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;Modify by nasiry for interrupt handle
    ;; Setup IRQ handler
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    InitVector
      ldr r2,=0x0
      ldr r3,=0x30000000

      ldr r0, [r2], #4
      str r0, [r3], #4
      cmp r2,#0x1000
      bne %b1
    InstallIrqIsr
     ldr r0,=HandleIRQ       ;This routine is needed
     ldr r1,=IsrIRQ   ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c
     str r1,[r0]

    就是把eboot搬运到ram以后再搬运最前端的1K代码到0x3000 0000,然后将IsrIRQ的地址装入HandleIRQ地址所代表的内存单元。

    中断部分的代码如下:

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;Modify by nasiry for ISR
    ;;2004.9.20
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    HandleIRQ     EQU   0x33ffff18
    HandleFIQ   EQU  0x33ffff1c

     STARTUPTEXT
     LEAF_ENTRY StartUp
    1 b  ResetHandler
     b  %B1  ;handler for Undefined mode
     b  %B1  ;handler for SWI interrupt
     b  %B1  ;handler for PAbort
     b  %B1  ;handler for DAbort
     b  %B1  ;reserved
     ;b  %B1    ;handler for IRQ interrupt
     b   IRQHandler   ;modify by nasiry for interrupt
     ;b  HandlerFIQ      ;handler for FIQ interrupt

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;modify by nasiry for add interrupt route for USB Fucntion
    ;;2004.9.20
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    IRQHandler
     sub sp,sp,#4      ;decrement sp(to store jump address)
     stmfd sp!,{r0}     ;PUSH the work register to stack(lr does't push because it return to original address)
     ldr     r0,=HandleIRQ  ;load the address of HandleXXX to r0
     ldr     r0,[r0]      ;load the contents(service routine start address) of HandleXXX
     str     r0,[sp,#4]      ;store the contents(ISR) of HandleXXX to stack
     ldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)
     

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    中断的安装就就此完成。
    由于C语言不能直接操作CPSR故而使用如下汇编代码构建开启中断的函数。
       MACRO
            RETURN
            bx      lr
            MEND
    ;-------------------------------------------------------------------------------
    ; INTERRUPTS_ON - enable interrupts
    ;-------------------------------------------------------------------------------
            LEAF_ENTRY INTERRUPTS_ON
            mrs     r0, cpsr                        ; (r0) = current status
            bic     r1, r0, #0x80                   ; clear interrupt disable bit
            msr     cpsr, r1                        ; update status register
            RETURN                                  ; return to caller

    ;-------------------------------------------------------------------------------
    ; INTERRUPTS_OFF - disable interrupts
    ;-------------------------------------------------------------------------------
            LEAF_ENTRY INTERRUPTS_OFF
            mrs     r0, cpsr                        ; (r0) = current status
            orr     r1, r0, #0x80                   ; set interrupt disable bit
            msr     cpsr, r1                        ; update status register

            RETURN                                  ; return to caller
    该代码完全遵循ATPCS,可以在armcc下直接使用。


     

    由于windowsCE编译器会在最前端的0x1000区域保留一个空区域所以上面所修改的中断向量都不会得到执行。如果使用偏移代码/数据副本的办法来填补这个区域的话,又必须保持一份原数据/代码,两份代码/数据之间的空间仅仅有4K所以偏移的办法基本上没有什么实际的用途。

    因此上面的代码不能用。


    另外就只有参考ATPCS动态通过C/Cpp装载中断向量的办法,通过 MMU构建一个位于ram中的高向量/低向量,然后通过构造的办法来实现中断向量。

    所以这样一来,ISR就没有必要放在fw.s中单独拿出来就行了。

    然后通过下列语句装载

    VectorIRQ =(unsigned)(0xEA000000)+(((unsigned)IRQHandler - (0x8c000000 + 0x18 + 0x8) )>>2);

  • 相关阅读:
    一卦,测一年运气
    测一下我心中想的事
    一卦,测一下我心里想的事
    这一卦,学到了不少东西
    癸山丁向下卦(七运)
    起卦测我心里想的事
    现在的卦,越来越看不懂了
    luogu P2759 奇怪的函数 |二分答案
    luogu P2515 [HAOI2010]软件安装 |Tarjan+树上背包
    luogu P2343 宝石管理系统 |分块+堆
  • 原文地址:https://www.cnblogs.com/nasiry/p/44843.html
Copyright © 2011-2022 走看看