📄 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, INTERWORK
.IFDEF AT91R40008
.INCLUDE "EB40008.inc"
.ENDIF
.IFDEF AT91R40807
.INCLUDE "EB40807.inc"
.ENDIF
.IFDEF AT91M40800
.INCLUDE "EB40800.inc"
.ENDIF
.EXTERN OSTCBCur
.EXTERN OSTCBHighRdy
.EXTERN OSPrioCur
.EXTERN OSPrioHighRdy
.EXTERN OSRunning
.EXTERN OSIntNesting
.EXTERN OSTimeTick
.EXTERN OSIntEnter
.EXTERN OSIntExit
.GLOBAL OSTickISR
.GLOBAL ARMDisableInt
.GLOBAL ARMEnableInt
.GLOBAL OSIntCtxSw
.GLOBAL OS_TASK_SW
.GLOBAL 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, #0x18 /* 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, =AIC_BASE
str r12, [r12, #AIC_EOICR] /* 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:
#- 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 r12, =AIC_BASE
str r12, [r12, #AIC_IVR]
# read the interrupt status reg to clear it
ldr r12,=TC0_BASE /* load tc0 base address */
ldr r12,[r12, #0x020] /* read from status register offse */
/* only for Timer using test...*/
# subs pc,lr,#4
/* only for Timer using test...*/
#- 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}
#- 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|ARM_MODE_IRQ
msr CPSR_c, r12
#- Mark the End of Interrupt on the AIC
ldr r12, =AIC_BASE
str r12, [r12, #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 + -