uCOSV2.52在mini2440上的移植解析1:OS_CPU_A.S

uCOSV2.52在mini2440上的移植解析1:OS_CPU_A.S

uCOS-II的移植实例要求用户编写4个简单的汇编语言函数:

OSStartHighRdy();

OSCtxSw();

OSIntCtxSw();

OSTickISR();

下面就开始分析uCOS-II在mini2440开发板上的ADS环境运行的移植细节。

/*关于mini2440的中断设置和ARM处理器工作的七种模式*/

SRCPND    EQU  0x4a000000    ; Source pending
INTPND    EQU  0x4a000010    ; Interrupt request status

rEINTPEND   EQU  0x560000a8
INTOFFSET   EQU  0x4a000014


USERMODE    EQU  0x10
FIQMODE     EQU  0x11
IRQMODE     EQU  0x12
SVCMODE     EQU  0x13
ABORTMODE   EQU  0x17
UNDEFMODE   EQU  0x1b
MODEMASK    EQU  0x1f
NOINT       EQU  0xc0

;*********************************************************************************************************
;                                    引入外部的函数

;*********************************************************************************************************/
 IMPORT  OSRunning
 IMPORT  OSTCBCur
 IMPORT  OSTCBHighRdy
 IMPORT  OSPrioCur
 IMPORT  OSPrioHighRdy
 IMPORT  OSIntNesting
 
   
 IMPORT  OSIntEnter
 IMPORT  OSIntExit
 IMPORT  OSTaskSwHook
 IMPORT  OSTimeTick
 
 IMPORT  HandleEINT0
 

 EXPORT  OSStartHighRdy
 EXPORT  OSCtxSw
 EXPORT  OSTickISR 
 EXPORT  OSIntCtxSw

 EXPORT  OSCPUSaveSR
 EXPORT  OSCPURestoreSR
 
 EXPORT  OS_CPU_IRQ_ISR
 
 
 AREA UCOS_ARM, CODE, READONLY
 
;*********************************************************************************************************
;                                          开始多任务
;                                       void OSStartHighRdy(void)
;
; The stack frame is assumed to look as follows:
;
;           Entry Point(Task Name)    (High memory)
;                               LR(R14)
;                               R12
;                               R11
;                               R10
;                               R9
;                               R8
;                               R7
;                               R6
;                               R5
;                               R4
;                               R3
;                               R2
;                               R1
;                               R0 : argument
; OSTCBHighRdy->OSTCBStkPtr --> CPSR        (Low memory)
;
; Note : OSStartHighRdy() MUST:
;           a) Call OSTaskSwHook() then,
;           b) Set OSRunning to TRUE,
;           c) Switch to the highest priority task.
;********************************************************************************************************** */
OSStartHighRdy 
 ;---------------------------------------------------------------------------------- 
 ; OSRunning = TRUE;
 ;---------------------------------------------------------------------------------- 
 
 MSR     CPSR_cxsf,#SVCMODE|NOINT     ;切换至SVC模式并使FIQ,IRQ无效
 
 BL  OSTaskSwHook            ;调用用户钩子函数OSTaskSwHook ,带返回地址(存至LR寄存器中)
 LDR  R0, =OSRunning          ; 初始化时置OSRunning = true

 MOV  R1, #1
 STRB  R1, [R0]

 ;----------------------------------------------------------------------------------  
 ;   SP = OSTCBHighRdy->OSTCBStkPtr;
 ;---------------------------------------------------------------------------------- 
 LDR  R0, =OSTCBHighRdy
 LDR  R0, [R0]        
 LDR  SP, [R0]        

 ;----------------------------------------------------------------------------------  
 ; 准备返回合适的模式

 ;---------------------------------------------------------------------------------- 
 LDMFD  SP!, {R0}    ;  向下压栈
 MSR  SPSR_cxsf, R0
 LDMFD  SP!, {R0-R12, LR, PC}^   ;spsr的值复制到cpsr


;**********************************************************************************************************
;                                                任务切换

;                                           void OSCtxSw(void)
;
; Note(s):     1) Upon entry:
;                 OSTCBCur      points to the OS_TCB of the task to suspend
;                 OSTCBHighRdy  points to the OS_TCB of the task to resume
;
;              2) The stack frame of the task to suspend looks as follows:
;                                                  
;                                                   PC                    (High memory)
;               LR(R14)     
;                                    R12
;                                     R11
;                                    R10
;                                     R9
;                                    R8
;                                    R7
;                                    R6
;                                    R5
;                                    R4
;                                    R3
;                                    R2
;                                    R1
;                                    R0
;       OSTCBCur->OSTCBStkPtr ----> CPSR     (Low memory)
;
;
;              3) The stack frame of the task to resume looks as follows:
;
;                 PC    (High memory)
;                                                   LR(R14) 
;                                     R12
;                                    R11
;                                    R10
;                                     R9
;                                    R8
;                                    R7
;                                     R6
;                                    R5
;                                    R4
;                                    R3
;                                    R2
;                                    R1
;                                     R0
;      OSTCBHighRdy->OSTCBStkPtr ----> CPSR     (Low memory)
;*********************************************************************************************************/
OSCtxSw
 
 STMFD SP!, {LR}           ;PC
 STMFD SP!, {R0-R12, LR}   ;R0-R12 LR
 MRS  R0,  CPSR       ;Push CPSR
 STMFD SP!, {R0} 
  
 ;----------------------------------------------------------------------------------
 ;   OSTCBCur->OSTCBStkPtr = SP
 ;----------------------------------------------------------------------------------  
 LDR  R0, =OSTCBCur
 LDR  R0, [R0]
 STR  SP, [R0]
 
 ;----------------------------------------------------------------------------------  
 ; OSTaskSwHook();
 ;--------------------------------------------------------------------------------- 
 BL   OSTaskSwHook

 ;----------------------------------------------------------------------------------   
 ; OSTCBCur = OSTCBHighRdy;
 ;---------------------------------------------------------------------------------- 
 
 LDR  R0, =OSTCBHighRdy
 LDR  R1, =OSTCBCur
 LDR  R0, [R0]
 STR  R0, [R1]
 
 ;----------------------------------------------------------------------------------  
 ; OSPrioCur = OSPrioHighRdy;
 ;----------------------------------------------------------------------------------  

 LDR  R0, =OSPrioHighRdy
 LDR  R1, =OSPrioCur
 LDRB R0, [R0]
 STRB R0, [R1]
 
 ;----------------------------------------------------------------------------------  
 ;  OSTCBHighRdy->OSTCBStkPtr;
 ;----------------------------------------------------------------------------------  
 LDR  R0, =OSTCBHighRdy
 LDR  R0, [R0]
 LDR  SP, [R0]

 ;---------------------------------------------------------------------------------- 
 ;恢复下一个新任务的寄存器信息
 ;---------------------------------------------------------------------------------- 
 LDMFD  SP!, {R0}  ;POP CPSR
 MSR  SPSR_cxsf, R0
 LDMFD  SP!, {R0-R12, LR, PC}^ 

 
;*********************************************************************************************************
;                                            TICK HANDLER

;uCOS要求用户提供一个周期性的时钟源以实现时间的延迟和超时功能
;
; Description: 
;     This handles all the Timer0(INT_TIMER0) interrupt which is used to generate the uC/OS-II tick.
;*********************************************************************************************************/

OSTickISR
 MOV     R5,LR 
 MOV  R1, #1
 MOV  R1, R1, LSL #10  ; Timer0 Source Pending Reg.逻辑左移
 LDR  R0, =SRCPND
 LDR     R2, [R0]
 ORR     R1, R1,R2
 STR  R1, [R0]

 LDR  R0, =INTPND
 LDR  R1, [R0]
 STR  R1, [R0]  

 ;----------------------------------------------------------------------------------  
 ; OSTimeTick();
 ;---------------------------------------------------------------------------------- 
 BL  OSTimeTick
 
   
 MOV    PC, R5          ; Return  
 
;*********************************************************************************************************
;                                ISR中执行任务切换功能
;                                        void OSIntCtxSw(void)
;
; Description: 1) This code performs a context switch if a higher priority task has been made ready-to-run
;                during an ISR.
;
;              2) The stack frame of the task to suspend looks as follows:
;
;               PC     (High memory)
;                                                   LR(R14)
;                                    R12
;                                     R11
;                                    R10
;                                     R9
;                                    R8
;                                    R7
;                                    R6
;                                    R5
;                                    R4
;                                    R3
;                                    R2
;                                    R1
;                                    R0
;                                    
;       OSTCBCur->OSTCBStkPtr ----> CPSR     (Low memory)
;
;
;              3) The stack frame of the task to resume looks as follows:
;
;                 PC     (High memory)
;                                                   LR(R14) 
;                                     R12
;                                    R11
;                                    R10
;                                     R9
;                                    R8
;                                    R7
;                                     R6
;                                    R5
;                                    R4
;                                    R3
;                                    R2
;                                    R1
;                                     R0
;      OSTCBHighRdy->OSTCBStkPtr ----> CPSR     (Low memory)
;*********************************************************************************************************/
OSIntCtxSw
 ;----------------------------------------------------------------------------------  
 ; Call OSTaskSwHook();
 ;---------------------------------------------------------------------------------- 
 BL   OSTaskSwHook
 
 ;----------------------------------------------------------------------------------   
 ; OSTCBCur = OSTCBHighRdy;
 ;----------------------------------------------------------------------------------  
 LDR  R0, =OSTCBHighRdy
 LDR  R1, =OSTCBCur
 LDR  R0, [R0]
 STR  R0, [R1]
 
 ;----------------------------------------------------------------------------------  
 ; OSPrioCur = OSPrioHighRdy;
 ;----------------------------------------------------------------------------------  
 LDR  R0, =OSPrioHighRdy
 LDR  R1, =OSPrioCur
 LDRB R0, [R0]
 STRB R0, [R1]
 
 ;----------------------------------------------------------------------------------  
 ;   SP = OSTCBHighRdy->OSTCBStkPtr;
 ;----------------------------------------------------------------------------------  
 LDR  R0, =OSTCBHighRdy
 LDR  R0, [R0]
 LDR  SP, [R0]
 
 ;---------------------------------------------------------------------------------- 
 ; Restore New Task context
 ;---------------------------------------------------------------------------------- 

 LDMFD  SP!, {R0}              ;POP CPSR
 MSR  SPSR_cxsf, R0
 LDMFD  SP!, {R0-R12, LR, PC}^ 
 

 
OS_CPU_IRQ_ISR  

 STMFD   SP!, {R1-R3}   ; We will use R1-R3 as temporary registers
;----------------------------------------------------------------------------
;   R1--SP
; R2--PC
;   R3--SPSR
;------------------------------------------------------------------------

 MOV     R1, SP
 ADD     SP, SP, #12             ;Adjust IRQ stack pointer
 SUB     R2, LR, #4              ;Adjust PC for return address to task

 MRS     R3, SPSR    ; Copy SPSR (Task CPSR)
 
  

 MSR     CPSR_cxsf, #SVCMODE|NOINT   ;Change to SVC mode

         ; SAVE TASK''S CONTEXT ONTO OLD TASK''S STACK
         
 STMFD   SP!, {R2}    ; Push task''s PC
 STMFD   SP!, {R4-R12, LR}  ; Push task''s LR,R12-R4
 
 LDMFD   R1!, {R4-R6}   ; Load Task''s R4-R6 from IRQ stack
 STMFD   SP!, {R4-R6}   ; Push Task''s R4-R6 to SVC stack
 STMFD   SP!, {R0}       ; Push Task''s R0 to SVC stack
 
 STMFD   SP!, {R3}    ; Push task''s CPSR
 
 LDR     R0,=OSIntNesting        ;OSIntNesting++ 嵌套层数增加
 LDRB    R1,[R0]
 ADD     R1,R1,#1
 STRB    R1,[R0]
 
 CMP     R1,#1                   ;if(OSIntNesting==1){
 BNE     %F1                      ;向后搜索lable为1的行
  
 LDR     R4,=OSTCBCur            ;OSTCBHighRdy->OSTCBStkPtr=SP;
 LDR     R5,[R4]
 STR     SP,[R5]                 ;}
 
1
 MSR    CPSR_c,#IRQMODE|NOINT    ;Change to IRQ mode to use IRQ stack to handle interrupt
 
 LDR     R0, =INTOFFSET
    LDR     R0, [R0]
      
    LDR     R1, IRQIsrVect
    MOV     LR, PC                          ; Save LR befor jump to the C function we need return back
    LDR     PC, [R1, R0, LSL #2]            ; Call OS_CPU_IRQ_ISR_handler();  
   
    MSR  CPSR_c,#SVCMODE|NOINT   ;Change to SVC mode
    BL   OSIntExit           ;Call OSIntExit
   
    LDMFD   SP!,{R4}               ;POP the task''s CPSR
    MSR  SPSR_cxsf,R4
    LDMFD   SP!,{R0-R12,LR,PC}^    ;POP new Task''s context

IRQIsrVect DCD HandleEINT0 
   
;*********************************************************************************************************
;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
;
; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II''s functions that need to
;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
;              into the CPU''s status register.
;
; Prototypes : OS_CPU_SR  OSCPUSaveSR(void);
;              void       OSCPURestoreSR(OS_CPU_SR cpu_sr);
;
;
; Note(s)    : 1) These functions are used in general like this:
;
;                 void Task (void *p_arg)
;                 {
;                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
;                     OS_CPU_SR  cpu_sr;
;                 #endif
;
;                          :
;                          :
;                     OS_ENTER_CRITICAL();             /* cpu_sr = OSCPUSaveSR();                */
;                          :
;                          :
;                     OS_EXIT_CRITICAL();              /* OSCPURestoreSR(cpu_sr);                */
;                          :
;                          :
;                 }
;
;              2) OSCPUSaveSR() is implemented as recommended by Atmel''s application note:
;
;                    "Disabling Interrupts at Processor Level"
;*********************************************************************************************************
OSCPUSaveSR
 MRS     R0, CPSR    ; Set IRQ and FIQ bits in CPSR to disable all interrupts
 ORR     R1, R0, #0xC0
 MSR     CPSR_c, R1
 MRS     R1, CPSR    ; Confirm that CPSR contains the proper interrupt disable flags
 AND     R1, R1, #0xC0
 CMP     R1, #0xC0
 BNE     OSCPUSaveSR    ; Not properly disabled (try again)
 MOV     PC, LR     ; Disabled, return the original CPSR contents in R0

OSCPURestoreSR
 MSR     CPSR_c, R0
 MOV     PC, LR
        
 END

uCOSV2.52在mini2440上的移植解析1:OS_CPU_A.S_第1张图片

你可能感兴趣的:(uCOSV2.52在mini2440上的移植解析1:OS_CPU_A.S)