OSStart()函数分析
多任务的的启动是通过调用OSStart()实现的,而在启动uc/os之前至少需要建立一个应用任务。
OSStart()函数源码
void OSStart (void)
{
INT8U y;
INT8U x;
if (OSRunning == FALSE) {//参数检验,多任务尚未启动
y = OSUnMapTbl[OSRdyGrp];//这几句通过uc/os设定最高优先级查找算法找出当前最高优先级
x = OSUnMapTbl[OSRdyTbl[y]];
OSPrioHighRdy = (INT8U)((y << 3) + x);
OSPrioCur = OSPrioHighRdy;//第一次开始多任务调度,最高优先级任务运行,即当前优先级和最高优先级一样
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; //通过最高优先级超找优先级TCB表获得最高优先级TCB
OSTCBCur = OSTCBHighRdy;//第一次启动,二者一样
OSStartHighRdy();//调用启动函数,实质上是将任务栈中保存的值弹回到CPU寄存器中,然后执行中断返回自指令,中断返回指令强制执行任务代码
}
}
Ø OSStartHighRdy()永远不返回到OSStart()
Ø 当OSSTART执行完后OSRunning为真,多任务已经启动
OSStartHighRdy()分析
void OSStartHighRdy(void)
{
_OSStartHighRdy();//该是一个软中断,通过软中断调用来实现多任务的启动
}
_OSStartHighRdy()分析
SoftwareInterrupt
LDR SP, StackSvc //重新设置堆栈指针,此时处理器处于管理模式。此处设置是因为在后面新任务堆栈内容进入CPU寄存器的过程用,用新任务的堆栈指针覆盖了管理模式的指针
STMFD SP!, {R0-R3, R12, LR}//保存环境,LR内存放的软中断返回地址。
MOV R1, SP // R1指向参数存储位置
MRS R3, SPSR //获得进入软中断前的CPSR,
TST R3, #T_bit //中断前是否是Thumb状态
LDRNEH R0, [LR,#-2] //是: 取得Thumb状态SWI号
BICNE R0, R0, #0xff00
LDREQ R0, [LR,#-4] //否: 取得arm状态SWI号
BICEQ R0, R0, #0xFF000000
//r0 = SWI号,R1指向参数存储位置
CMP R0, #1
LDRLO PC, =OSIntCtxSw
LDREQ PC, =__OSStartHighRdy //SWI 0x01为第一次任务切换
BL SWI_Exception
LDMFD SP!, {R0-R3, R12, PC}^//恢复寄存器
StackSvc DCD (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)
__OSStartHighRdy分析
MSR CPSR_c, #(NoInt | SYS32Mode)//进入系统模式
//告诉uC/OS-II自身已经运行OSRunning==1;
LDR R4, =OSRunning
MOV R5, #1
STRB R5, [R4]
BL OSTaskSwHook //调用钩子函数
LDR R6, =OSTCBHighRdy//获得存放最高优先级TCB地址的地址
LDR R6, [R6]//获得当前最高优先级TCB地址
B OSIntCtxSw_1//任务堆栈内容进入CPU,启动最高优先级任务
AREA SWIStacks, DATA, NOINIT,ALIGN=2
SvcStackSpace SPACE SVC_STACK_LEGTH * 4 //管理模式堆栈空间
OSIntCtxSw_1分析
OSIntCtxSw_1
LDR R4, [R6] //获取新任务堆栈指针,此时指针指向栈底(压入了数据),此时处理器模式依然是管理模式
ADD SP, R4, #17*4 //17寄存器CPSR,OsEnterSum,R0-R12,LR,SP移动任务堆栈的指针,使的SP指向任务堆栈的栈顶(次数数据并未弹出)
LDR LR, [SP, #-8]//获得LR_USR,
MSR CPSR_c, #(NoInt | SVC32Mode) //进入管理模式
MOV SP, R4 //设置堆栈指针,此处修改了管理模式的指针使得其指向新任务的堆栈栈底,此处修改了管理模式的堆栈指针,故在每一次进入软中断都要从新设置管理模式堆栈指针。
LDMFD SP!, {R4, R5} ;CPSR,OsEnterSum
;恢复新任务的OsEnterSum
LDR R3, =OsEnterSum
STR R4, [R3]
MSR SPSR_cxsf, R5 ;恢复CPSR
LDMFD SP!, {R0-R12, LR, PC }^ ;//此处LR其实是LR_SVC是没有什么实际作用的,只不过为了方便指针的自动移动而出栈PC,LR_USR在前面已经恢复。
Ø 函数分析是基于LPC2200的
Ø 任务栈内数据存放数据
任务堆栈 |
任务入栈的其他数据 |
PC |
LR |
R12 |
R11 |
R10 |
…… |
…… |
R3 |
R2 |
R1 |
R0 |
CPSR |
OSEnterSum |
空闲空间 |