📄 os_cpu_a.s
字号:
#;*
#;* File: os_cpu_a.s
#;*
#;* (c) Copyright ARM Limited 1999. All rights reserved.
#;*
#;* ARM Specific code
#;*
#;*
#;
#; Functions defined in this module:
#;
#; void ARMDisableInt(void) /* disable interrupts when in SVC */
#; void ARMEnableInt(void) /* enable interrupts when in SVC */
#; void OS_TASK_SWAP(void) /* context switch */
#; void OSStartHighRdy(void) /* start highest priority task */
.EQU SwiV, 0x08
.EQU IrqV, 0x18
.EQU FiqV, 0x1C
.EQU NoInt, 0x80
.EQU SVC32Mode, 0x13
.EQU IRQ32Mode, 0x12
.EQU FIQ32Mode, 0x11
.EQU OSEnterSWI, 0x00
.EQU BIT_TIMER0, (0x1<<13)
.EQU I_ISPC, 0x1e00024
.EQU INTMSK, 0x1e0000c
.EQU OS_EnterOS, 0xff
# AREA subr, CODE, READONLY
#; External symbols we need the addresses of
.extern OSTCBCur
.extern OSTCBHighRdy
.extern OSPrioCur
.extern OSPrioHighRdy
.extern OSTaskSwHook
.extern OSRunning
/*
addr_OSTCBCur:
.WORD OSTCBCur
addr_OSTCBHighRdy:
.WORD OSTCBHighRdy
addr_OSPrioCur:
.WORD OSPrioCur
addr_OSPrioHighRdy:
.WORD OSPrioHighRdy
*/
.extern OSTaskSwHook
.extern need_to_swap_context
.extern OSTimeTick
.extern OSIntEnter
.extern OSIntExit
.extern IrqStart
.extern IrqFinish
.extern OutDebug
.extern BreakPoint
.global IRQContextSwap
.global TickHandler
.global OSTickISR
OSTickISR:
MOV ip, sp
STMDB sp!, {fp, ip, lr, pc}
SUB fp, ip, #4
# BL OSIntEnter
BL OSTimeTick
# BL OSIntExit
LDMDB fp, {fp, sp, pc}
#--------------------------------------------------------------------------------------
#; void DisableInt(void)
#; void EnableInt(void)
#;
#; Disable and enable IRQ and FIQ preserving current CPU mode.
#;
.global ARMDisableInt
ARMDisableInt:
STMDB sp!, {r0}
MRS r0, CPSR
ORR r0, r0, #NoInt
MSR CPSR_cxsf, r0
LDMIA sp!, {r0}
MOV pc, lr
.global ARMEnableInt
ARMEnableInt:
STMDB sp!, {r0}
MRS r0, CPSR
BIC r0, r0, #NoInt
MSR CPSR_cxsf, r0
LDMIA sp!, {r0}
MOV pc, lr
.global ARMIsDisableInt
ARMIsDisableInt: /*return value [disable: 1 enable: 0]*/
MRS a1, CPSR
AND a1, a1, #NoInt
MOV pc, lr
#; void OSStartHighRdy(void)
#;
#; Start the task with the highest priority#;
#;
#--------------------------------------------------------------------------------------
.global OSStartHighRdy
OSStartHighRdy:
#; Need to be in a supervisor mode first, because of using spsr
SWI OS_EnterOS
#; Call OSTaskSwHook()
BL OSTaskSwHook
#; Set OSRunning to TRUE
MOV R0,#1
LDR R1,=OSRunning
STRB R0,[R1]
#; Get stack ptr for task to resume (lives in OSTCBHighRdy->OSTCBStkPtr)
LDR R1,=OSTCBHighRdy
LDR R1,[R1]
LDR R0,[R1,#0] /*; OSTCBStkPtr is at +0*/
#;regdump "Restoring context (OSStartHighRdy)", R0
#; Restore saved context & return to task
LDMFD R0!,{R1,R14} /*; SPSR & return addr*/
MSR SPSR_all,R1
LDMFD R0,{R0-R14}^ /*; Restore USR mode regs R0-R14*/
NOP
MOVS PC,R14 /*; PC=ret addr & CPSR=SPSR*/
#--------------------------------------------------------------------------------------
.global OS_TASK_SW
OS_TASK_SW:
# Call from OSSched()
# New Task Context switch
MOV R2,R14
MRS R1,CPSR /*; Take copy of current PSR*/
# SWI OS_EnterOS /*; enter SVC mode*/
BIC R0,R1,#0x1f
ORR R0,R0,#0x92 /*; IRQ32 + interrupts off*/
MSR CPSR_all,R0
NOP
MSR SPSR_all,R1 /*; SPSR=old PSR*/
# ADD R14,R2,#4 /*; R14_irq=return addr*/
ADD R14,R2,#0 /*; R14_irq=return addr*/
#; Now in a state just like as if at 0x18
B OSCtxSw
#--------------------------------------------------------------------------------------
#;*********************************************************************************************************
#; PERFORM A CONTEXT SWITCH (From task level)
#; void OSCtxSw(void)
#;
#;*********************************************************************************************************
OSCtxSw:
STMFD R13!,{R14} /*; Stack return addr*/
#; Save current task context
STMDB R13,{R13}^ /*; Determine R13_usr*/
LDMDB R13,{R14}
STMFD R14,{R0-R14}^ /*; Stack USR mode regs R0-R14*/
MRS R1, SPSR
SUB R0,R14,#15*4
LDMFD R13!,{R14}
STMFD R0!,{R1,R14} /*; Stack SPSR & return addr*/
#; Store stack ptr of task (lives in OSTCBCur->OSTCBStkPtr)
LDR R1,=OSTCBCur
LDR R1,[R1]
STR R0,[R1,#0] /*; OSTCBStkPtr is at +0 */
#; regdump "Saving context (OSCtxSw)", R0
#; Call user definable OSTaskSwHook()
BL OSTaskSwHook
#; Set current task to new task
LDR R2,=OSTCBHighRdy
LDR R3,=OSTCBCur
LDR R4,=OSPrioHighRdy
LDR R5,=OSPrioCur
LDR R0,[R2]
LDRB R1,[R4]
STR R0,[R3]
STRB R1,[R5]
#; Get stack ptr for task to resume (lives in OSTCBHighRdy->OSTCBStkPtr)
LDR R1,=OSTCBHighRdy
LDR R1,[R1]
LDR R0,[R1,#0] /*; OSTCBStkPtr is at +0*/
#; regdump "Restoring context (OSCtxSw)", R0
#; Restore saved context & return to task
LDMFD R0!,{R1,R14} /*; SPSR & return addr*/
MSR SPSR_all,R1
LDMFD R0,{R0-R14}^ /* ; Restore USR mode regs R0-R14*/
NOP
MOVS PC,R14 /*; PC=ret addr & CPSR=SPSR */
#;*********************************************************************************************************
#; PERFORM A CONTEXT SWITCH (From an ISR)
#; void OSIntCtxSw(void)
#;
#;*********************************************************************************************************
.global OSIntCtxSw
OSIntCtxSw:
#; Remove all registers on IRQ stack so far
#; This means the order in which things were called before calling this
#; In our case, this means OSIntExit, the ISR routine and then anything which
#; called the ISR (eg; a HAL like NedHAL)
#; Regs stacked WILL BE DIFFERENT DEPENDING ON COMPILER VERSION
#; Remove OSIntExit() stacked regs from ISR stack
#; v2.5: {r14}
#; v2.0: {r11,r12,r14,pc}
#;ADD R13,R13,#4 ; v2.5
# SystemIrqHandler call ISR_IrqHandler, ISR_IrqHandler call OSTickISR,
# OSTickISR call OSIntExit(), OsIntExit then
# call OSIntCtxSw, so we need to remove this stack structure, otherwise after
# a certain time, there will be no more IRQ stack left
LDMDB fp, {fp,sp,lr} /* simulate quit OSIntExit stack */
# LDMDB fp, {fp,sp,lr} /* simulate quit OSTickISR stack */
LDMDB fp, {fp, sp, lr} /* simulate quit ISR_IrqHandler orISR_FiqHandler stack */
LDMFD sp!, {r0-r12, lr} /* simulate quit SystemIrqHandler stack */
SUB lr,lr,#4 /* IRQ return address */
#; Perform normal task swap
B OSCtxSw
# END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -