📄 os_cpu_a.s
字号:
;*******************************************************************************************
;OS_CPU_A.s
PRESERVE8
AREA OS_CPU_A, CODE, READONLY
CODE32
; 定义于ucos_ii.h中的外部变量
;OS_EXT OS_TCB *OSTCBCur; /* Pointer to currently running TCB */
;OS_EXT OS_TCB *OSTCBHighRdy; /* Pointer to highest priority TCB R-to-R */
;OS_EXT INT8U OSPrioCur; /* Priority of current task */
;OS_EXT INT8U OSPrioHighRdy; /* Priority of highest priority task */
;OS_EXT BOOLEAN OSRunning; /* Flag indicating that kernel is running */
IMPORT OSTCBCur
IMPORT OSTCBHighRdy
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
IMPORT OSRunning
;*******************************************************************************************
EXPORT OSStartHighRdy
;功能:
;1)SP=OSTCBHighRdy->OSTCBStkPtr
;2)OSTCBCur->OSTCBHighRdy
;3)将当前优先级最高的任务切换到运行态,本任务只在系统开始运行前运行一次!该函数不会返回到
; 调用者OSStart().
OSStartHighRdy
LDR r4,=OSRunning ;起始状态时OSRunning显然为0
MOV r5,#1
STRB r5,[r4] ;直接置1,标志系统进入运行状态
IMPORT OSTaskSwHook
BL OSTaskSwHook
LDR r4, =OSTCBCur ; 当前任务TCB地址
LDR r5, =OSTCBHighRdy ; 最高优先级任务的TCB地址
LDR r5, [r5] ; TCB的第一个元素就是OSTCBStkPtr,即任务的栈指针
LDR sp, [r5] ; 更新当前任务的栈指针为预先设置的值
; SP=OSTCBHighRdy->OSTCBStkPtr
STR r5, [r4] ; 将优先级最高的任务设置为当前任务
; OSTCBCur=OSTCBHighRdy
LDMFD sp!, {r4} ; 从任务堆栈中恢复上下文(context)
;MSR SPSR_cxsf, r4 ; usr,sys模式无SPSR
LDMFD sp!, {r4} ;
MSR CPSR_cxsf, r4 ; CPSR --- SYS Mode
LDMFD sp!, {r0-r12, lr, pc }
; 任务运行
;*******************************************************************************************
EXPORT OS_TASK_SW
;功能
;1)保存当前任务上下文
;2)更新系统变量OSPrioCur = OSPrioHighRdy
;3)OSTCBCur->OSTCBStkPtr=SP 保存SP到当前任务控制块
;4)获得即将进入运行状态的高优先级任务的栈指针SP=OSTCBHighRdy->OSTCBStkPtr
;5)更新系统变量OSTCBCur->OSTCBHighRdy
;6)切换任务上下文
OS_TASK_SW
STMFD sp!, {lr} ; 保存 pc
STMFD sp!, {lr} ; 保存 lr
;OS_TASK_SW这个函数,在系统调用它时是在当前任务最后失去CPU时,当前任务再次
;获得CPU时,其恰好在OS_TASK_SW调用完毕后的那个位置,因此,lr被放入pc
;在栈中的位置,即任务继续开始执行的位置;此外,lr放在栈中的位置也是无关
;紧要的,因为,这个子函数返回时的lr是无意义的
STMFD sp!, {r0-r12} ; 保存任务上下文
MRS r4, CPSR
STMFD sp!, {r4} ; save current PSR
;MRS r4, SPSR ; 任务运行于SYS模式,无SPSR,栈中的CPSR与SPSR相同
STMFD sp!, {r4} ; 构成一致的堆栈结构
IMPORT OSTaskSwHook
BL OSTaskSwHook
LDR r4, =OSPrioCur ; 开始切换任务
LDR r5, =OSPrioHighRdy
LDRB r6, [r5] ; 更新系统变量
STRB r6, [r4] ; OSPrioCur = OSPrioHighRdy
LDR r4, =OSTCBCur ; 获取当前任务的栈指针
LDR r5, [r4]
STR sp, [r5] ; 保存当前任务的栈指针
; OSTCBCur->OSTCBStkPtr=SP 保存SP到当前任务控制块
; 当前运行任务的上下文保存完毕
LDR r6, =OSTCBHighRdy ; 高优先级任务的TCB地址
LDR r6, [r6]
LDR sp, [r6] ; 取得高优先级任务的栈指针
; SP=OSTCBHighRdy->OSTCBStkPtr 更新SP为即将运行的任务的栈指针
STR r6, [r4] ; 更新系统变量
; OSTCBCur = OSTCBHighRdy
LDMFD sp!, {r4}
;MSR SPSR_cxsf, r4 ; 运行在sys模式下,无需SPSR的更新
LDMFD sp!, {r4}
MSR CPSR_cxsf, r4
LDMFD sp!, {r0-r12, lr, pc}
; 高优先级任务的上下文恢复完成,切换到高优先级任务运行
;*******************************************************************************************
EXPORT OSIntCtxSw
OSIntCtxSw
;新的代码,实现了中断的嵌套(其实现依赖于底层向量的处理代码)
;该函数运行依赖于调用IrqHandler之前的模式转换和栈构造
;运行于SYS模式,其首先调整SP_sys指针到下图中SPSR处
;后半部分与OSCtxSw相同
;该函数是不返回的,进入时堆栈结构是已知的,除了原来构造的
;标准栈,还压入了一些多余的内容(可以参看编译后的汇编代码)
;而且这些"多余的内容"和编译器、编译器的设置都有关
;irq的栈结构,进入IrqHandler前,sp指向的恰好是构造的标准栈顶,但是,
;由于函数中又调用了别的函数于是进入OSIntCtxSw后还得调整SP
;**********************************************************************
;低 r4 r14 spsr cpsr r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 lr PC 高
;**********************************************************************
ADD sp,sp,#16 ;调整SP_sys指向标准栈结构
;在汇编中找到压入堆栈的多余数据,通过调整SP来去掉
;这是很关键的步骤,具体请参考uC/OS-II的手册
;后面的内容和OSCtxSw的后半部分相同,依次为
;1)OSPrioCur = OSPrioHighRdy
;2)OSTCBCur->OSTCBStkPtr=SP 保存SP到当前任务控制块
;3)SP=OSTCBHighRdy->OSTCBStkPtr
;4)OSTCBCur=OSTCBHighRdy
;5)切换上下文
;6)高优先级任务运行
IMPORT OSTaskSwHook
BL OSTaskSwHook
LDR r4, =OSPrioCur
LDR r5, =OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4] ; OSPrioCur = OSPrioHighRdy
LDR r4, =OSTCBCur ; 获得当前任务的TCB地址
LDR r5, [r4]
STR sp, [r5] ;
; OSTCBCur->OSTCBStkPtr=SP 保存SP到当前任务控制块
LDR r6, =OSTCBHighRdy ; 获得高优先级任务的TCB地址
LDR r6, [r6]
LDR sp, [r6] ; 获得高优先级任务的栈指针
; SP=OSTCBHighRdy->OSTCBStkPtr 更新SP为即将运行的任务
STR r6, [r4] ; 更新系统变量OCTCBCur
; OSTCBCur = OSTCBHighRdy
LDMFD sp!, {r4}
;MSR SPSR_cxsf, r4 ; 运行在sys模式下,无需SPSR的更新
LDMFD sp!, {r4}
MSR CPSR_cxsf, r4
LDMFD sp!, {r0-r12, lr, pc}
; 上下文切换完成,切换到高优先级任务运行
;*******************************************************************************************
; 定义于ucos_ii.h中的外部变量
;OS_EXT INT8U OSIntNesting; /* Interrupt nesting level */
IMPORT OSIntNesting
;*******************************************************************************************
END
;*******************************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -