⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_cpu_a.s

📁 嵌入式操作系统源代码ucos2.61
💻 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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -