chinaye1 发表于 2011-6-3 10:02:24

arm的FIQ中断裸机特别写法及与ucos管理中断或不管理中断情况下处理,及最近遇到问题的

本人用的是2440开发板,一直以来网上都没找到fiq中断的写法,最后自己写了个如下这样的:

IRQ仍然为向量中断,(貌似44b0的时候数据手册还强调这个,2440都没提了)

1、裸机和ucos不管理中断
2440init.s中为

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

        ldr        r9,=INTOFFSET
        ldr        r9,
        ldr        r8,=HandleEINT0
        add        r8,r8,r9,lsl #2
        ldr        r8,
        str        r8,
        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,

普通写法,中断处理程序都是带__irq关键字的。好了关键部分了,rINTMOD = 0x00002000;设置想使用FIQ模式的中断,如这里是Timer3
然后就这样 pISR_FIQ = (unsigned int)Timer3Int;这里直接将中断处理程序放在了 FIQ异常的地址处,这也导致缺点明显--只能有一个FIQ中断存在。其它普通中断还这样写pISR_TIMER0 = (unsigned int)OSTickISR;

1、ucos管理中断,中断处理程序都是不带__irq关键字的

;Setup IRQ handler
        ldr        r0,=HandleIRQ       ;This routine is needed
        ldr        r1, =OS_CPU_IRQ_ISR ;modify by txf, for ucos
        str        r1,

; Setup FIQ handler
        ldr        r0,=HandleFIQ       ;This routine is needed
        ldr        r1, =OS_CPU_FIQ_ISR ;modify by txf, for ucos
        str        r1,


OS_CPU_IRQ_ISR就不说了,在OS_CPU_A.s中

OS_CPU_FIQ_ISR --------程序来源于uCos2-2.83-AN-1014这本书

      STMFD   SP!, {R1-R4}                   ; PUSH WORKING REGISTERS ONTO FIQ STACK
      MOV   R1, SP                         ; Save   FIQ stack pointer
      SUB   R2, LR,#4                      ; Adjust PC for return address to task
      MRS   R3, SPSR                     ; Copy SPSR (i.e. interrupted task''s CPSR)
      MOV   R4, R3

      AND   R4, R4, #0x1F                  ; Isolate Mode bits
      CMP   R4, #IRQMODE                   ; See if we interrupted an IRQ
      BEQ   OS_CPU_FIQ_ISR_2               ; Branch if yes.


                                             ; ===== FIQ interrupted Task =====
      MSR   CPSR_c, #(NOINT | SVCMODE)            ; Change to SVC mode
                                             ; SAVE TASK'S CONTEXT ONTO TASK'S STACK
      STMFD   SP!, {R2}                      ;    Push task''s Return PC
      STMFD   SP!, {LR}                      ;    Push task''s LR
      STMFD   SP!, {R5-R12}                  ;    Push task''s R12-R5

      LDMFD   R1!, {R5-R8}                   ;    Move R1-R4 from FIQ to SVC stack
      STMFD   SP!, {R5-R8}
      STMFD   SP!, {R0}                      ;    Push task's R0 onto task's stack
      STMFD   SP!, {R3}                      ;    Push task's CPSR (i.e. FIQ's SPSR)
                                             ; HANDLE NESTING COUNTER
      LDR   R0, =OSIntNesting            ; OSIntNesting++;
      LDRB    R1,
      ADD   R1, R1,#1
      STRB    R1,

      CMP   R1, #1                         ; if (OSIntNesting == 1){
      BNE   OS_CPU_FIQ_ISR_1
      LDR   R4, =OSTCBCur                ;   OSTCBCur->OSTCBStkPtr = SP
      LDR   R5,
      STR   SP,                      ; }

OS_CPU_FIQ_ISR_1
      MSR   CPSR_c, #(NOINT | FIQMODE) ; Change to FIQ mode
      ADD   SP, SP, #16                  ; Adjust FIQ stack pointer
      LDR   R0, =Timer0Int                              ; OS_CPU_FIQ_ISR_Handler();
      MOV   LR, PC
      BX      R0

      MSR   CPSR_c, #(NOINT | SVCMODE) ; Change to SVC mode
      LDR   R0, =OSIntExit               ; OSIntExit();
      MOV   LR, PC
      BX      R0

                                             ; RESTORE NEW TASK''S CONTEXT
      LDMFD   SP!, {R4}                      ;    Pop new task''s CPSR
      MSR   SPSR_cxsf, R4

      LDMFD   SP!, {R0-R12,LR,PC}^         ;    Pop new task''s context
      
OS_CPU_FIQ_ISR_2
                                             ; SAVE IRQ'S CONTEXT ONTO FIQ'S STACK
      STMFD   SP!, {R0-R7,LR}                ;    Push shared registers
                                             ; HANDLE NESTING COUNTER
      LDR   R0, =OSIntNesting                    ; OSIntNesting++;    (Notify uC/OS-II)
      LDRB    R1,
      ADD   R1, R1,#1
      STRB    R1,


      LDR   R0, =Timer0Int                                   ; OS_CPU_FIQ_ISR_Handler();
      MOV   LR, PC
      BX      R0
                                             ; HANDLE NESTING COUNTER
      LDR   R0, =OSIntNesting            ; OSIntNesting--;
      LDRB    R1,                      ;   NO need to call OSIntExit() ret to IRQ
      SUB   R1, R1, #1
      STRB    R1,

      LDMFD   SP!, {R0-R7,LR}                ; Pop IRQ''s context
      LDMFD   SP!, {R1-R4}                   ; PULL WORKING REGISTERS ONTO FIQ STACK
      SUBS    PC, LR, #4                     ; Return to IRQ
       

以上均由本人测试通过,各位可放心使用,关于OSTickISR中断,一直以来都好使用没外接TOUT的Timer4,但最近碰到了死机问题,最后使用Timer0,
并通过rPRIORITY = 0x00080000;改变其在所有IRQ中断中的优先级就改善了这种死机情况,但中断过高后仍然会死机!而用裸机不加ucos系统就没问题。不知道原因,特别是用ucos管理中断时候更容易死机,详细情况见俺的另一个帖子。


最后最近在debug过程中遇到了这个问题

这样写

t = b + 0.5;
a = 100.0 / t;

和这样写


a = 100.0 /(b + 0.5);

一样吗??不一样 这里注意t 和 a 是 int 还是 float


最最后,国际惯例,转载请注明出处,用于商业用途请跟本人联系,欢迎坛友讨论!

male123 发表于 2012-5-21 13:38:42

楼主玩过ARM7吗?
请教:ARM7的FIQ怎么写啊?
页: [1]
查看完整版本: arm的FIQ中断裸机特别写法及与ucos管理中断或不管理中断情况下处理,及最近遇到问题的