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,下节介绍