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

📄 os_cpu_a.s

📁 研一的ucosii在s3c2440的移植源代码
💻 S
字号:
;********************************************************************************************************
;                                               uC/OS-II
;                                         The Real-Time Kernel
;
;                          (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
;                                          All Rights Reserved
;
; File : OS_CPU_A.ASM
; By   : Jean J. Labrosse
;********************************************************************************************************

;********************************************************************************************************
;                                               ARM Port
;
;                 Target           : ARM (Includes ARM7, ARM9)
;                 Ported by        : Michael Anburaj
;                 URL              : http://geocities.com/michaelanburaj/    Email : michaelanburaj@hotmail.com
;
;********************************************************************************************************


;Pre-defined constants
USERMODE    EQU         0x10
FIQMODE     EQU         0x11
IRQMODE     EQU         0x12
SVCMODE     EQU         0x13
ABORTMODE   EQU         0x17
UNDEFMODE   EQU         0x1b
MODEMASK    EQU         0x1f
NOINT       EQU         0xc0
TBIT        EQU         0x20


        AREA  UCOS_ARM, CODE, READONLY

;*********************************************************************************************************
;                                          START MULTITASKING
;                                       void OSStartHighRdy(void)
;
; Note : OSStartHighRdy() MUST:
;           a) Call OSTaskSwHook() then,
;           b) Set OSRunning to TRUE,
;           c) Switch to the highest priority task.
;*********************************************************************************************************

        IMPORT  OSTaskSwHook
        IMPORT  OSRunning
        IMPORT  OSTCBHighRdy

        EXPORT  OSStartHighRdy

OSStartHighRdy  

        bl OSTaskSwHook             ; Call user defined task switch hook

        ldr r4,=OSRunning           ; Indicate that multitasking has started
        mov r5,#1
        strb r5,[r4]

        ldr r4,=OSTCBHighRdy        ; Get highest priority task TCB address

        ldr r4,[r4]                 ; get stack pointer
        ldr sp,[r4]                 ; switch to the new stack

        ldmfd sp!,{r4}              ; pop new task's spsr
        ldmfd sp!,{r4}              ; pop new task's psr
        msr SPSR_cxsf,r4
        ldmfd sp!,{r0-r12,lr,pc}^   ; pop new task's r0-r12,lr & pc

;*********************************************************************************************************
;                                PERFORM A CONTEXT SWITCH (From task level)
;                                           void OSCtxSw(void)
;
; Note(s):    Upon entry, 
;             OSTCBCur     points to the OS_TCB of the task to suspend
;             OSTCBHighRdy points to the OS_TCB of the task to resume
;
;*********************************************************************************************************

        IMPORT  OSTCBCur
        IMPORT  OSTaskSwHook
        IMPORT  OSTCBHighRdy
        IMPORT  OSPrioCur
        IMPORT  OSPrioHighRdy

        EXPORT  OSCtxSw

OSCtxSw
; Special optimised code below:
        stmfd sp!,{lr}              ; push pc (lr should be pushed in place of PC)
        ldr lr,=0xdead1eaf          ; Just a dummy value is pushed for lr (for actual lr is safe inside callers stack)
        stmfd sp!,{r0-r12,lr}       ; push lr & register file
        mrs r4,cpsr
    [ THUMB_TASKS
        orr r4,r4,#TBIT
    ]
        stmfd sp!,{r4}              ; push current psr
        mrs r4,spsr
        stmfd sp!,{r4}              ; push current spsr

        ; OSPrioCur = OSPrioHighRdy
        ldr r4,=OSPrioCur
        ldr r5,=OSPrioHighRdy
        ldrb r6,[r5]
        strb r6,[r4]
        
        ; Get current task TCB address
        ldr r4,=OSTCBCur
        ldr r5,[r4]
        str sp,[r5]                 ; store sp in preempted tasks's TCB

        bl OSTaskSwHook             ; call Task Switch Hook

        ; Get highest priority task TCB address
        ldr r6,=OSTCBHighRdy
        ldr r6,[r6]
        ldr sp,[r6]                 ; get new task's stack pointer

        ; OSTCBCur = OSTCBHighRdy
        str r6,[r4]                 ; set new current task TCB address

        ldmfd sp!,{r4}              ; pop new task's spsr
        ldmfd sp!,{r4}              ; pop new task's psr
        msr SPSR_cxsf,r4

        ldmfd sp!,{r0-r12,lr,pc}^   ; pop new task's r0-r12,lr & pc


;*********************************************************************************************************
;                                PERFORM A CONTEXT SWITCH (From an ISR)
;                                        void OSIntCtxSw(void)
;
; Note(s): This function only flags a context switch to the ISR Handler
;
;*********************************************************************************************************

        IMPORT  OSIntCtxSwFlag

        EXPORT  OSIntCtxSw

OSIntCtxSw

        ;OSIntCtxSwFlag = True
        ldr r0,=OSIntCtxSwFlag
        mov r1,#1
        str r1,[r0]
        bx lr
        

;*********************************************************************************************************
;                                            IRQ HANDLER
;
;        This handles all the IRQs
;        Note: FIQ Handler should be written similar to this
;
;*********************************************************************************************************

        IMPORT  C_IRQHandler
        IMPORT  OSIntEnter
        IMPORT  OSIntExit

        IMPORT  OSIntCtxSwFlag
        IMPORT  OSTCBCur
        IMPORT  OSTaskSwHook
        IMPORT  OSTCBHighRdy
        IMPORT  OSPrioCur
        IMPORT  OSPrioHighRdy

        EXPORT  UCOS_IRQHandler
UCOS_IRQHandler

        ; Fix the return address
        sub lr,lr,#4
        stmfd sp!,{r0-r3,r12,lr}

        bl OSIntEnter
        bl C_IRQHandler
        bl OSIntExit

        ; Is OSIntCtxSwFlag == True ?
        ldr r0,=OSIntCtxSwFlag
        ldr r1,[r0]
        cmp r1,#1
        beq _IntCtxSw

        ldmfd sp!,{r0-r3,r12,pc}^


_IntCtxSw
        ; OSIntCtxSwFlag = False
        mov r1,#0
        str r1,[r0]

        ; Get old task's sp & lr
        mrs r0,spsr
        orr r0,r0,#NOINT
        bic r0,r0,#TBIT
        msr cpsr_c,r0
        mov r1,sp
        mov r2,lr
        bic r0,r0,#MODEMASK
        orr r0,r0,#IRQMODE
        msr cpsr_c,r0

        ; Unwind IRQ's sp without poping r0-r3
        mov r3,sp
        add sp,sp,#(4*4)
        ldmfd sp!,{r12,lr}

        stmfd r1!,{r2,lr}           ; push old task's pc & lr
        stmfd r1!,{r4-r12}          ; push old task's r12-r4

        ; Get r0-r3 from IRQ's stack
        mov r6,r1
        ldmfd r3,{r0-r3}
        stmfd r6!,{r0-r3}           ; push old task's r3-r0
        
        mrs r3,spsr
        stmfd r6!,{r3}              ; push old task's psr
        stmfd r6!,{r3}              ; push old task's spsr (don't care)
        
        ; OSPrioCur = OSPrioHighRdy
        ldr r4,=OSPrioCur
        ldr r5,=OSPrioHighRdy
        ldrb r5,[r5]
        strb r5,[r4]
        
        ; Get current task's TCB address
        ldr r4,=OSTCBCur
        ldr r5,[r4]
        str r6,[r5]                 ; store sp in preempted tasks's TCB

        bl OSTaskSwHook             ; call Task Switch Hook

        ; Get highest priority task's TCB address
        ldr r6,=OSTCBHighRdy
        ldr r6,[r6]
        ldr r5,[r6]                 ; get new task's stack pointer

        ; OSTCBCur = OSTCBHighRdy
        str r6,[r4]                 ; set new current task TCB address

        ldmfd r5!,{r4}              ; pop new task's spsr (don't care)
        ldmfd r5!,{r4}              ; pop new task's psr

        ; Leave IRQ mode
        orr r0,r4,#NOINT
        bic r0,r0,#TBIT
        msr cpsr_c,r0

        msr spsr_cxsf,r4
        mov sp,r5

        ldmfd sp!,{r0-r12,lr,pc}^   ; pop new task's r0-r12,lr & pc


;*********************************************************************************************************
;                                   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.
;
;              OS_CPU_SR OSCPUSaveSR()
; Arguments  : none
;
; Returns    : OS_CPU_SR
;
;              OSCPURestoreSR(OS_CPU_SR cpu_sr)
; Arguments  : OS_CPU_SR
;
; Returns    : none
;
; Note(s)    : These functions are used in general like this,
;
;            void Task (void *data)
;            {
;                    #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); */
;                         :
;                         :
;            }
;*********************************************************************************************************

        EXPORT  OSCPUSaveSR
OSCPUSaveSR

        mrs r0,CPSR
        orr r1,r0,#NOINT
        msr CPSR_c,r1
        bx lr


        EXPORT  OSCPURestoreSR
OSCPURestoreSR

        msr CPSR_c,r0
        bx lr


        END

⌨️ 快捷键说明

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