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

📄 os_cpu_a.s

📁 ucos-ii在ARM7 (S3C44B0)上的移植完整代码
💻 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
#
#********************************************************************************************************



        .text

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

        .EXTERN  OSTaskSwHook
        .EXTERN  OSRunning
        .EXTERN  OSTCBHighRdy

        .global  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
        msr SPSR_cxsf,r4
        ldmfd sp!,{r4}              @ pop new task's psr
        msr CPSR_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
#
#*********************************************************************************************************

        .EXTERN  OSTCBCur
        .EXTERN  OSTaskSwHook
        .EXTERN  OSTCBHighRdy
        .EXTERN  OSPrioCur
        .EXTERN  OSPrioHighRdy

        .global  OSCtxSw

OSCtxSw:
# Special optimised code below:
        stmfd sp!,{lr}              @ push pc (lr should be pushed in place of PC)
        stmfd sp!,{r0-r12,lr}       @ push lr & register file
        mrs r4,cpsr
        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
        msr SPSR_cxsf,r4
        ldmfd sp!,{r4}              @ pop new task's psr
        msr CPSR_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
#
#*********************************************************************************************************

        .EXTERN  OSIntCtxSwFlag

        .global  OSIntCtxSw

OSIntCtxSw:

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

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

        .EXTERN  Timer0Interrupt
        .EXTERN  OSIntEnter
        .EXTERN  OSIntExit

        .EXTERN  OSIntCtxSwFlag
        .EXTERN  OSTCBCur
        .EXTERN  OSTaskSwHook
        .EXTERN  OSTCBHighRdy
        .EXTERN  OSPrioCur
        .EXTERN  OSPrioHighRdy

		.equ NOINT, 0xc0

        .global  TickHandler
TickHandler:

        stmfd sp!,{r0-r3,r12,lr}

        bl OSIntEnter
        bl Timer0Interrupt
        bl OSIntExit

        ldr r0,=OSIntCtxSwFlag
        ldr r1,[r0]
        cmp r1,#1
        beq _IntCtxSw

        ldmfd sp!,{r0-r3,r12,lr}
        subs pc,lr,#4


_IntCtxSw:
        mov r1,#0
        str r1,[r0]

        ldmfd sp!,{r0-r3,r12,lr}
        stmfd sp!,{r0-r3}
        mov r1,sp
        add sp,sp,#16
        sub r2,lr,#4

        mrs r3,spsr
        orr r0,r3,#NOINT
        msr spsr_c,r0

        ldr r0,=.+8
        movs pc,r0

        stmfd sp!,{r2}              @ push old task's pc
        stmfd sp!,{r4-r12,lr}       @ push old task's lr,r12-r4
        mov r4,r1                   @ Special optimised code below
        mov r5,r3
        ldmfd r4!,{r0-r3}
        stmfd sp!,{r0-r3}           @ push old task's r3-r0
        stmfd sp!,{r5}              @ push old task's psr
        mrs r4,spsr
        stmfd sp!,{r4}              @ push old task's spsr
        
        @ OSPrioCur = OSPrioHighRdy
        ldr r4,=OSPrioCur
        ldr r5,=OSPrioHighRdy
        ldrb r5,[r5]
        strb r5,[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
        msr SPSR_cxsf,r4
        ldmfd sp!,{r4}              @ pop new task's psr
        msr CPSR_cxsf,r4

        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)# */
#                         :
#                         :
#            }
#*********************************************************************************************************

        .global  OSCPUSaveSR
OSCPUSaveSR:

        mrs r0,CPSR
        orr r1,r0,#NOINT
        msr CPSR_c,r1
        mov pc,lr


        .global  OSCPURestoreSR
OSCPURestoreSR:

        msr CPSR_c,r0
        mov pc,lr


        .END
        

⌨️ 快捷键说明

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