OSStart(void)
void OSStart (void)
{
if (OSRunning == OS_FALSE) {
OS_SchedNew(); /* Find highest priority's task priority number */
OSPrioCur = OSPrioHighRdy; //最高优先级赋给 当前优先级
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* 从TCB链表中取出最高优先级 赋给 最高级TCB */
OSTCBCur = OSTCBHighRdy; //最高优先级赋给 当前优先级
OSStartHighRdy(); /* */
}
}
OS_SchedNew(); 详解见http://my.oschina.net/u/274829/blog/263287
OSStartHighRdy
// 系统执行命令为汇编代码
OSStartHighRdy
;设置pendSV中断优先级 0xff
LDR R4, =NVIC_SYSPRI2 ; PendSV 中断
LDR R5, =NVIC_PENDSV_PRI ;0xff
STR R5, [R4] ;将R5寄存器值赋到R4中
;设置堆栈指针为0
MOV R4, #0 ; set the PSP to 0 for initial context switch call
MSR PSP, R4 ;MSR将R4值赋给PSP
; OSRunning = TRUE
LDR R4, =OSRunning ;将=OSRunning指令地址放到R4中
MOV R5, #1
STRB R5, [R4] ;将R5寄存器数据写入R4地址内存中
;切换到最高优先级的任务
LDR R4, =NVIC_INT_CTRL ;rigger the PendSV exception (causes context switch)
LDR R5, =NVIC_PENDSVSET
STR R5, [R4] ;切换到最高级中断 使能PendSV SysTick中断
CPSIE I ;开中断的汇编代码
OSStartHang
B OSStartHang ;should never get here
以上是任务创建的全过程;cpu的PSP初始化为0来运行我们系统中优先级最高的任务并将OSRunning标记为true来表示我们的内核开始运行了。
PendSV_Handler
PendSV_Handler
CPSID I ; 关所以中断
MRS R0, PSP ; PSP是当前进程堆栈的指针,将PSP赋值给R0
CBZ R0, PendSV_Handler_Nosave ; 如果R0为0时跳转到PendSV_Handler_Nosave
;已经存在任务 保存正在运行的任务
SUBS R0, R0, #0x20 ; 偏移0x20的位置用来保存R4至R11
STM R0, {R4-R11} ;将剩下的R4至R11寄存器保存在此进程的堆栈中
LDR R1, =p_OSTCBCur
; OSTCBCur->OSTCBStkPtr = SP; 即OSTCBCur->OSTCBStkPtr这个保存当前的栈尾,以便下次弹出
LDR R1, [R1]
STR R0, [R1] ; R0 is SP of process being switched out
;此时,整个上下文的过程已经被保存
PendSV_Handler_Nosave
PUSH {R14} ; Save LR exc_return value
LDR R0, =OSTaskSwHook ; OSTaskSwHook(); 这里用于用户扩展
BLX R0
POP {R14}
;将最高优先级任务赋给当前优先级
LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
LDR R1, =OSPrioHighRdy ;将当前优先级变量指向最高优先级
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =p_OSTCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R1, =p_OSTCBHighRdy ;TCB表也一样
LDR R2, [R1]
STR R2, [R0]
;到这里,[R2]保存的是新的进程的堆栈指针SP
LDR R0, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr;
LDM R0, {R4-R11} ; 弹出其它寄存器,和前面的是一个逆过程
ADDS R0, R0, #0x20 ;和前面的逆过程对比可知
MSR PSP, R0 ; 将R0中的SP赋值给PSP寄存器
ORR LR, LR, #0x04 ; 确保异常返回时使用进程堆栈
CPSIE I ;开中断
BX LR ; 异常返回将恢复那些自动出栈的剩余寄存器
;跳到当前任务 开始运行
这里是系统默认中断做的事:主要工作有判断是否第一次运行、将最高级任务赋给当前任务,然后将放到cpu寄存器运行,最高优先级任务开始运行。
系统任务切换则是靠OSTimeDly,下节介绍