📄 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -