原创 UCOS-II中OS_CPU_IRQ_ISR函数移植

2011-1-19 16:36 2322 7 7 分类: MCU/ 嵌入式

在有中断发生时,程序跳到OS_CPU_IRQ_ISR处执行。OS_CPU_IRQ_ISR函数在OS_CPU_A.S中。

OS_CPU_IRQ_ISR

                                   

        STR     R3,  [SP, #-4]!   1 ; PUSH WORKING REGISTERS ONTO IRQ STACK

        STR     R2,  [SP, #-4]!   2

        STR     R1,  [SP, #-4]!   3

       

        MOV     R1, SP          4               ; Save   IRQ stack pointer

       

        ADD     SP, SP,#12        5             ; Adjust IRQ stack pointer

       

        SUB     R2, LR,#4         6             ; Adjust PC for return address to task

 

        MRS     R3, SPSR         7    ; Copy SPSR (i.e. interrupted task's CPSR) to R3

       

        MSR     CPSR_c, #(NO_INT | SYS32_MODE) ;8 Change to SYS mode

 

                                               ; SAVE TASK'S CONTEXT ONTO TASK'S STACK

        STR     R2,  [SP, #-4]!                9;    Push task's Return PC

        STR     LR,  [SP, #-4]!                10;    Push task's LR

        STR     R12, [SP, #-4]!                11;    Push task's R12-R4

        STR     R11, [SP, #-4]!                12

        STR     R10, [SP, #-4]!                13

        STR     R9,  [SP, #-4]!               14

        STR     R8,  [SP, #-4]!                15

        STR     R7,  [SP, #-4]!                16

        STR     R6,  [SP, #-4]!                17

        STR     R5,  [SP, #-4]!                18

        STR     R4,  [SP, #-4]!                19

       

        LDR     R4,  [R1], #4    20 ;    Move task's R1-R3 from IRQ stack to SYS stack

        LDR     R5,  [R1], #4                  21

        LDR     R6,  [R1], #4                  22

        STR     R6,  [SP, #-4]!                  23

        STR     R5,  [SP, #-4]!                  24

        STR     R4,  [SP, #-4]!                  25

       

        STR     R0,  [SP, #-4]!             26;    Push task's R0    onto task's stack

        STR     R3,  [SP, #-4]!          27   ;    Push task's CPSR (i.e. IRQ's SPSR)

                

                                               ; HANDLE NESTING COUNTER

        LDR     R0, =OSIntNesting       28       ; OSIntNesting++;

        LDRB    R1, [R0]                29

        ADD     R1, R1,#1               30

        STRB    R1, [R0]               31

 

        CMP     R1, #1                 32        ; if (OSIntNesting == 1) {

        BNE     OS_CPU_IRQ_ISR_1     33

 

        LDR     R4, =OSTCBCur    34        ;     OSTCBCur->OSTCBStkPtr = SP

        LDR     R5, [R4]            35

        STR     SP, [R5]             36          ; }

 

OS_CPU_IRQ_ISR_1

        MSR     CPSR_c, #(NO_INT | IRQ32_MODE) 37; Change to IRQ mode (to use the IRQ stack to handle interrupt)

       

        LDR     R0, =OS_CPU_IRQ_ISR_Handler  38 ; OS_CPU_IRQ_ISR_Handler();

        MOV     LR, PC                  39

        BX      R0                       40

       

        MSR     CPSR_c, #(NO_INT | SYS32_MODE) 41; Change to SYS mode

        

        BL      OSIntExit                    42 ; OSIntExit();

       

                                              ; RESTORE TASK'S CONTEXT and RETURN TO TASK

        LDR     R4,  [SP], #4                 43;    pop new task's CPSR

        MSR     CPSR_cxsf, R4                44

        LDR     R0,  [SP], #4                45 ;    pop new task's context

        LDR     R1,  [SP], #4                46

        LDR     R2,  [SP], #4                47

        LDR     R3,  [SP], #4                48

        LDR     R4,  [SP], #4                49

        LDR     R5,  [SP], #4                50

        LDR     R6,  [SP], #4                51

        LDR     R7,  [SP], #4                52

        LDR     R8,  [SP], #4                53

        LDR     R9,  [SP], #4                54

        LDR     R10, [SP], #4                 55

        LDR     R11, [SP], #4                 56

        LDR     R12, [SP], #4                 57

        LDR     LR,  [SP], #4                 58

        LDR     PC,  [SP], #4                 59

在分析这个移植代码前,先了解下发生IRQ中断时,ARM的处理流程:

1、  会把当前的CPSR的值拷贝到SPSR_irq

2、  把PC的值拷贝到LR_irq

3、  强制进入IRQ异常模式

4、  强制进入ARM状态

5、  禁止IRQ中断

6、  PC=0X18,跳转到OS_CPU_IRQ_ISR

上面这些都是硬件自动完成的。

在PC跳转到OS_CPU_IRQ_ISR后,已经进入IRQ模式,这时的SP指向的是IRQ模式下的堆栈,也就是说SP的实际物理地址是R13_irq。

下面分析程序:

1-3:把R1,R2,R3的值保存到IRQ的堆栈,只保存这3个寄存器的原因是下面使用到了这3个寄存器。

4:把当前SP的值保存在R1中

5:因为在保存R1,R2,R3进堆栈时,SP减了12,所以这里让SP+12,重新指向IRQ堆栈的起始位置。

6:LR_irq减4得到的值保存在R2中,LR_irq的值不变。这里减4和ARM的3级流水线取指有关系。

7:把SPSR_irq的值保存进R3,SPSR_irq的值是进入中断前的CPSR值

8:修改CPSR的值,进入系统模式

9:因为系统模式和用户模式的寄存器一样,所以系统模式的SP就是用户模式的SP。把R2的值压入堆栈,这句是保存用户程序的返回PC值

10:保存任务的LR值进堆栈

11-19:保存任务的R12-R4寄存器值进堆栈

20-25:把保存在IRQ堆栈里的R1,R2,R3寄存器的值保存到系统堆栈里,也就保存到用户任务堆栈。对应第1-4条指令就可以看明白。

26:把R0的值保存进堆栈

27:把R3保存的值,也就是SPSR_irq的值保存进堆栈。SPSR_irq的值就是进入中断前的CPSR值。

到这里为止,所有的寄存器值都已经保存到了任务堆栈里。

28-31:OSIntNesting加1,OSIntNesting是内核为中断嵌套的层数定义的一个全局变量。每进入一次中断,该变量加1,退出一次中断,该变量减一。中断全部处理完,该变量为0

32-36:判断是否是中断的第一层,如果是,立即把堆栈指针保存到这个任务的任务控制块OS_TCB中。如果有中断嵌套,跳转到OS_CPU_IRQ_ISR_1处执行。

这么做是UCOS中规定的。中断第一层要保存任务堆栈指针,这个好理解,如果发生中断嵌套,整个处理流程是怎样的?还没完全弄清楚,下次再写篇文章单独探讨这个问题。

37:进入IRQ模式,利用IRQ模式下的堆栈来处理中断程序。

38:把函数OS_CPU_IRQ_ISR_Handler()的地址传给R0。OS_CPU_IRQ_ISR_Handler()是执行中断处理的函数,下面会讲到。

39:把当前PC的值保存进LR_irq。作为下面调用OS_CPU_IRQ_ISR_Handler()函数后的返回地址。

40:跳转到OS_CPU_IRQ_ISR_Handler()处执行。

OS_CPU_IRQ_ISR_Handler()不是UCOS-II自带的函数,是用户自己加的。我是在LPC2214上移植的,下面的寄存器都是LPC2214的中断寄存器。函数如下:

void OS_CPU_IRQ_ISR_Handler(void)

{

    PFNCT pfnct;

  

    pfnct = (PFNCT)VICVectAddr;     /* Read the interrupt vector from the VIC */

    while (pfnct != (PFNCT)0) {     /* Handle ALL interrupting devices */

        (*pfnct)();                 /* Call ISR for interrupting device */

        pfnct = (PFNCT)VICVectAddr; /* Read the interrupt vector from the VIC */

    }

}

VICVectAddr寄存器存的就是中断处理函数的地址,当这个值不为0时,就跳到对应的中断处理函数处执行。这个值为0,说明所有的中断处理函数都已经执行完成,程序返回到第41条指令处。

41:进入系统模式

42:调用OSIntExit函数。注意使用BL指令跳转时,会自动把下一条指令地址拷贝到LR中,而使用BX不会。在OSIntExit函数中,OSIntNesting会减1,同时判断是否执行任务调度。如果要进行任务调度,会调用函数OSIntCtxSw();执行OSIntCtxSw()后,就会跳转到新的任务去执行,不会执行43条以下的指令了。

43-59:如果没有进行任务调度。就把任务堆栈中的保存的寄存器值全部恢复到寄存器中。在任务中断的断点处继续运行。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条