www.pudn.com > ucos2.61.rar > Os_cpu_a.s


;------------------------------------------------------------------------------ 
;-         ATMEL Microcontroller Software Support  -  ROUSSET  - 
;------------------------------------------------------------------------------ 
; The software is delivered "AS IS" without warranty or condition of any 
; kind, either express, implied or statutory. This includes without 
; limitation any warranty or condition with respect to merchantability or 
; fitness for any particular purpose, or against the infringements of 
; intellectual property rights of others. 
;----------------------------------------------------------------------------- 
;- File source          : os_cpu.s 
;- Object               : AT91 Ucos specific assembly functions 
;- 
;- 1.0 21/08/00 EL      : creation 
;------------------------------------------------------------------------------ 
 
 
 
    AREA  |subr|, CODE, READONLY 
 
 
    INCLUDE ..\..\..\include\at91m55800a.inc 
 
I_BIT                   EQU     0x80 
F_BIT                   EQU     0x40 
T_BIT                   EQU     0x20 
ARM_MODE_USER           EQU     0x10 
ARM_MODE_FIQ            EQU     0x11 
ARM_MODE_IRQ            EQU     0x12 
ARM_MODE_SVC            EQU     0x13 
ARM_MODE_ABORT          EQU     0x17 
ARM_MODE_UNDEF          EQU     0x1B 
ARM_MODE_SYS            EQU     0x1F 
NOINT                   EQU     0xc0     
     
    IMPORT OSTCBCur 
    IMPORT OSTCBHighRdy 
    IMPORT OSPrioCur 
    IMPORT OSPrioHighRdy 
    IMPORT OSRunning 
    IMPORT OSIntNesting 
    IMPORT OSTimeTick 
    IMPORT OSIntEnter 
    IMPORT OSIntExit 
            
    EXPORT OSTickISR 
    EXPORT ARMDisableInt 
    EXPORT ARMEnableInt 
    EXPORT OSIntCtxSw 
    EXPORT OS_TASK_SW  
     
    EXPORT OSStartHighRdy 
 
 
 
 
;-------------------------------------------------------------------------------------- 
ARMDisableInt                    
    mrs     r12, CPSR           ;get current CPU mode 
    orr     r12, r12, #I_BIT    ;set the interrupt disable mode bit 
    msr     CPSR_c, r12          
    bx  lr                   
;-------------------------------------------------------------------------------------- 
 
;-------------------------------------------------------------------------------------- 
ARMEnableInt 
    mrs     r12, CPSR             ;move current processor status into reg 12 
    bic     r12, r12, #I_BIT      ;clear the interrupt disable bit 
    msr     CPSR_c, r12            
    bx  lr                     
;-------------------------------------------------------------------------------------- 
 
;-------------------------------------------------------------------------------------- 
OSIntCtxSw 
 
; Interrupt Exit if higher priority task ready to run 
; New Task Context switch  
 
    add sp,sp, #8                   ; adjust sp to compensate for the call to OSIntExit        
    msr     CPSR_c, #0x92           ; switch to IRQ mode and disable IRQ's                                      ; the following 2 lines keep the stack 
                                       
    ldmfd   sp!, {r12, r14}         ; restore the stack  
    ldmfd   sp!, {r12}    
 
    ldr     r12, =AT91C_BASE_AIC 
    str     r12, [r12, #0x130]  ; write any value to EOICR to signal end of int 
    msr     CPSR_c, #ARM_MODE_SYS   ; switch back to system mode with IRQ and FIQ enabled 
        
    b   OSCtxSw                 ; perform the context switch 
                                       
;-------------------------------------------------------------------------------------- 
 
;-------------------------------------------------------------------------------------- 
OS_TASK_SW 
; Call from OSSched() 
; New Task Context switch   
    stmfd   sp!, {r0-r12, r14}  ; store current context 
    b   OSCtxSw                 ; perform the context switch                                    
;-------------------------------------------------------------------------------------- 
 
;-------------------------------------------------------------------------------------- 
OSCtxSw                              
    mrs     r4, CPSR                ; load current psr to r4 
    stmfd   sp!, {r4}               ; save current PSR to stack 
    mrs     r4, SPSR                ; load saved psr to r4 
    stmfd   sp!, {r4}               ; saved saved psr to stack 
 
  ;OSPrioCur = OSPrioHighRdy 
    ldr     r4, =OSPrioCur          ; load the current priority pointer 
    ldr     r5, =OSPrioHighRdy      ; load address of highest prio task 
    ldrb    r6, [r5]                ; load value of highest prio task 
    strb    r6, [r4]                ; store value of highest in current 
 
  ; Get current task TCB address 
    ldr     r4, =OSTCBCur           ; load pointer 
    ldr     r5, [r4]                ; load current tcb sp 
    str     sp, [r5]                ; store sp in preempted tasks's TCB 
 
  ; Get highest priority task TCB address 
    ldr r6, =OSTCBHighRdy 
    ldr     r6, [r6]                ; get highrdy's sp 
    ldr     sp, [r6]                ; set sp = highrdy[sp] 
 
  ; OSTCBCur = OSTCBHighRdy 
    str     r6, [r4]                ; set new current task TCB address 
    ldmfd   sp!, {r4}               ; load saved SPSR from stack 
    msr     SPSR_c, r4                ; spsr = saved spsr 
    ldmfd   sp!, {r4}               ; load saved cpsr from stack 
    msr     CPSR_c, r4                ; cpsr = saved cpsr 
    ldmfd   sp!, {r0-r12, r14}      ; restore r0-r12 and lr interworking 
    bx      r14                     ; interworking branch on lr 
;-------------------------------------------------------------------------------------- 
 
;-------------------------------------------------------------------------------------- 
OSStartHighRdy 
        ; Set OSRunning == TRUE 
    ldr     r4, =OSRunning          ;point r4 to OSRunning       
    mov     r5, #1                  ;move 1 into r5  
    strb    r5, [r4]                ;store r5 in [r4] 
 
        ; Get current task TCB address 
    ldr     r4, =OSTCBCur           ;point to current tcb   
 
        ; Get highest priority task TCB address 
    ldr     r5, =OSTCBHighRdy       ;point to highest tcb    
    ldr     r5, [r5]                ; get stack pointer      
    ldr     sp, [r5]                ; sp = highrdy[sp]       
    str     r5, [r4]                ; set current tcb = highrdy tcb 
 
    ldmfd   sp!, {r4}               ; get spsr       
    ldmfd   sp!, {r4}               ; get cpsr new state from top of the stack       
    msr     CPSR_c, r4              ; set cpsr = saved CPSR      
    ldmfd   sp!, {r0-r12, r14}      ; restore registers r0-r12 and lr    
    bx  r14                         ; branch on new task 
;-------------------------------------------------------------------------------------- 
 
;-------------------------------------------------------------------------------------- 
OSTickISR 
;- Adjust and save LR_irq in IRQ stack 
        sub     r14, r14, #4 
        stmfd   sp!, {r14} 
 
;- Save SPSR and r0 in IRQ stack 
        mrs     r14, SPSR 
        stmfd   sp!, {r12, r14} 
 
;- Write in the IVR to support Protect Mode 
;- No effect in Normal Mode 
;- De-assert the NIRQ and clear the source in Protect Mode 
        ldr     r14, =AT91C_BASE_AIC 
        str     r14, [r14, #0x100] ;#AT91C_AIC_IVR 
     
;read the interrupt status reg to clear it 
        ldr     r12,=AT91C_BASE_TC0         ; load tc0  base address 
        ldr     r12,[r12, #0x020]       ; read from status register offse 
 
;- Enable Interrupt and Switch in SYS Mode 
        mrs     r12, CPSR 
        bic     r12, r12, #I_BIT 
        orr     r12, r12, #ARM_MODE_SYS 
        msr     CPSR_c, r12               
 
;- Save scratch/used registers and LR in SYS Stack 
        stmfd   sp!, { r0-r12,r14} 
                     
        ldr     r12, =OSIntEnter          
        mov     r14,pc                    
        bx      r12                     ; Branch to OsIntEnter  
        ldr     r12, =OSTimeTick          
        mov     r14,pc                    
        bx      r12                      ; Branch to OsTimeTick            
        ldr     r12, =OSIntExit           
        mov     r14,pc                    
        bx      r12                      ; Branch to OSIntExit  
  
; Interrupt Exit if no higher priority task ready to run 
          
; restore interrupted task   
;- Restore scratch/used registers and LR from System Stack 
        ldmfd   sp!, { r0-r12, r14} 
                     
;- Disable Interrupt and switch back in IRQ mode 
        mrs r12, CPSR 
        bic     r12, r12, #ARM_MODE_SYS 
        orr     r12, r12, #I_BIT:OR:ARM_MODE_IRQ 
        msr     CPSR_c, r12 
         
;- Mark the End of Interrupt on the AIC 
        ldr     r12, =AT91C_BASE_AIC 
        str r12, [r12, #0x130]  ;#AT91C_AIC_EOICR 
;- Restore SPSR_irq and r0 from IRQ stack 
        ldmfd   sp!, {r12, r14} 
        msr     SPSR_c, r14 
;- Restore adjusted  LR_irq from IRQ stack directly in the PC 
        ldmfd   sp!, {pc}^ 
        END 
;-------------------------------------------------------------------------------------- 
 
 
END