📄 os_cpu_a.s
字号:
;--------------------------------------------------------------------------------------------------
; - uC/OS-II的内核调度程序 - 作者:焦海波 -
;--------------------------------------------------------------------------------------------------
;- 文件名称 : os_cpu_a.s
;- 功能描述 : 提供任务级的和中断级的内核调度程序
;- 版本 : V0.1
;- 建立时间 : 2007/05/08 10:00
;--------------------------------------------------------------------------------------------------
INCLUDE at91sam7x256/include/AT91SAM7X256.inc
INCLUDE arm7tdmi/include/arm.inc
;--------------------------------------------------------------------------------------------------
;- 导入的一些外部符号
;--------------------------------------------------------------------------------------------------
IMPORT OSRunning
IMPORT OSTCBHighRdy
IMPORT OSTCBCur
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
IMPORT blIsNeedCtxSw
IMPORT OSTaskSwHook
IMPORT OSIntEnter
IMPORT OSIntExit
IMPORT OSTimeTick
IMPORT OSStartPIT
;--------------------------------------------------------------------------------------------------
;- 允许导出的符号
;--------------------------------------------------------------------------------------------------
EXPORT ARMCoreDisableIntExt
EXPORT ARMCoreRestoreIntStatus
EXPORT OSStartHighRdy
EXPORT OSCtxSw
EXPORT OSIntCtxSwExt
EXPORT IRQHandler
EXPORT FIQHandler
;--------------------------------------------------------------------------------------------------
;- 宏定义区
;--------------------------------------------------------------------------------------------------
MACRO ;- OSTCBCur->OSTCBStkPtr = SP
__macEditStkPtr $R0, $SP
LDR $R0, =OSTCBCur
LDR $R0, [$R0]
STR $SP, [$R0]
MEND
MACRO ;- OSPrioCur = OSPrioHighRdy
__macEditOSPrioCur $R0, $R1
LDR $R0, =OSPrioCur
LDR $R1, =OSPrioHighRdy
LDRB $R1, [$R1]
STRB $R1, [$R0]
MEND
MACRO ;- OSTCBCur = OSTCBHighRdy
__macEditOSTCBCur $R0, $R1
LDR $R0, =OSTCBCur
LDR $R1, =OSTCBHighRdy
LDR $R1, [$R1]
STR $R1, [$R0]
MEND
MACRO ;- 结束内核调度中断
__macEndInt $R0
LDR $R0, =AT91C_BASE_AIC ;- 结束中断
STR $R0, [$R0, #AIC_EOICR]
MEND
MACRO
__macIntHandler $IntVR ;- 中断处理入口,完成用户自定义的中断处理和任务调度
SUB LR, LR, #4
STMFD SP!, {R0-R3, LR}
BL OSIntEnter ;- 进入用户自定义的中断服务子函数
LDR R0, =AT91C_BASE_AIC
LDR R0, [R0, $IntVR]
LDR LR, =.+8
BX R0
BL OSIntExit ;- 退出中断,看看是否进行任务切换
LDR R0, =blIsNeedCtxSw ;- 判断是否需要任务切换
LDRB R1, [R0]
CMP R1, #1
BEQ OSIntCtxSwExt
__macEndInt R0 ;- 结束中断
LDMFD SP!, {R0-R3, PC}^
MEND
;--------------------------------------------------------------------------------------------------
;- 代码区
;--------------------------------------------------------------------------------------------------
AREA OSKernelSchedular, CODE, READONLY
;--------------------------------------------------------------------------------------------------
;- 临界处理函数
ARMCoreDisableIntExt
MRS R0,CPSR ;- 将CPSR寄存器的值传送到参数寄存器R0中
__DisableInt
ORR R1,R0,#I_BIT:OR:F_BIT
MSR CPSR_c,R1 ;- 进行判断的目的是确认中断禁止操作已经成功后再开始临界处理
MRS R1,CPSR
AND R1,R1,#I_BIT:OR:F_BIT
CMP R1,#I_BIT:OR:F_BIT
BNE __DisableInt
BX LR ;- 返回调用函数并返回原来的CPSR值
ARMCoreRestoreIntStatus
MSR CPSR_c, R0
BX LR
;--------------------------------------------------------------------------------------------------
;- 启动uC/OS-II,开始多任务处理,OSStart()调用该函数
OSStartHighRdy
LDR R0, =OSRunning ;- OSRunning = TRUE
MOV R1, #1
STRB R1, [R0]
BL OSTaskSwHook ;- 调用任务切换钩子函数
BL OSStartPIT ;- 开启定时器
LDR R0, =OSTCBHighRdy ;- 获得最高优先级任务的堆栈地址
LDR R0, [R0]
LDR SP, [R0]
LDMFD SP!, {R0}
MSR CPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}
;--------------------------------------------------------------------------------------------------
;- 任务级的任务切换函数
OSCtxSw
STMFD SP!, {LR} ;- 实际上,LR保存的返回地址就是当前任务恢复运行后的开始
STMFD SP!, {R0-R12, LR} ;- ……地址,这个值会被恢复到PC指针寄存器中
MRS R0, CPSR
STMFD SP!, {R0}
__macEditStkPtr R0, SP ;- 由于前面进行了入栈操作,所以在这里应该修改当前任务控
;- ……制块TCB中保存的堆栈指针,OSTCBCur->OSTCBStkPtr = SP
BL OSTaskSwHook ;- 调用任务切换钩子函数
__macEditOSPrioCur R0, R1 ;- OSPrioCur = OSPrioHighRdy
__macEditOSTCBCur R0, R1 ;- OSTCBCur = OSTCBHighRdy
LDR SP, [R1] ;- SP = OSTCBHighRdy->OSTCBStkPtr
LDMFD SP!, {R0} ;- 把高优先级任务从堆栈中推入到CPU的寄存器中,恢复高优先级任务的运行
MSR CPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}
;--------------------------------------------------------------------------------------------------
;- 中断处理入口,这两个入口函数提供中断服务及任务调度功能
IRQHandler
__macIntHandler #AIC_IVR
FIQHandler
__macIntHandler #AIC_FVR
OSIntCtxSwExt
MOV R1, #0 ;- blIsNeedCtxSw = OS_FALSE
STRB R1, [R0]
LDMFD SP!, {R0-R3, LR} ;- LR出栈
STMFD SP!, {R0-R3} ;- 由于R0-R3寄存器在下面的代码中仍然使用,所以这里再一次入栈保护
MOV R0, LR ;- 保存当前正在运行的任务的返回地址
MRS R1, SPSR ;- 保存当前正在运行的任务的CPSR寄存器的值
MOV R2, SP ;- 保存IRQ堆栈地址
ADD SP, SP, #16 ;- 在返回到先前的模式之前,调整IRQ(或FIQ)堆栈指针到正确位置,因为
;- ……模式切换后,IRQ(或FIQ)堆栈中保存的R0-R3寄存器会被转移到任务
;- ……堆栈中,这实际上相当于出栈操作
ORR R3, R1, #I_BIT:OR:F_BIT ;- 切换到先前的模式之前,必须禁止中断,当前处理不能被中断打断
MSR SPSR_c, R3 ;- 切换到先前的模式,这实际上就是被中断的任务所处的模式
LDR R3, =.+8
MOVS PC, R3
STMFD SP!, {R0} ;- 保存当前任务的PC指针
STMFD SP!, {R4-R12, LR} ;- 保存当前任务使用的工作寄存器、LR
MOV R4, R1 ;- 把R0-R3寄存器的值从IRQ(或FIQ)堆栈转移到任务堆栈,并将当前任务的CPSR入栈
MOV R5, R2
LDMFD R5!, {R0-R3}
STMFD SP!, {R0-R3}
STMFD SP!, {R4} ;- 保存当前任务的CPSR寄存器
__macEditStkPtr R0, SP ;- OSTCBCur->OSTCBStkPtr = SP
BL OSTaskSwHook
__macEditOSPrioCur R0, R1 ;- OSPrioCur = OSPrioHighRdy
__macEditOSTCBCur R0, R1 ;- OSTCBCur = OSTCBHighRdy
LDR SP, [R1] ;- SP = OSTCBHighRdy->OSTCBStkPtr
LDMFD SP!, {R0} ;- 从堆栈中恢复CPSR
MSR CPSR_cxsf, R0
__macEndInt R0 ;- 结束中断
LDMFD SP!, {R0-R12, LR, PC} ;- 恢复高优先级任务的运行
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -