OS_Sched()
函数流程:查找已经就绪的最高优先级的任务,并使用任务堆栈,继续运行该任务。
//OSRdyGrp就绪组:代表8个一组的任务优先级组,从0到7或15
//OSUnMapTbl[]就绪表数组:数组中每一项是一个字节,第N项代表了第N个就绪组,字节数据代表了该优先级组中的优先级偏移(范围是从0~7,就是低三位)
//利用以上两者,覆盖了64(8*8)个优先级或者256(16*16)个优先级。
//此时就绪组可能多个位被置位,表示可能多个优先级组有就绪任务;就绪表数组某个元素代表了某组中多个任务中的某个任务就绪,如何查找出最高优先级且已经就绪的那个?就绪组里的最低置位项N;就绪表数组中第N项里的最低置位项
1、当没有中断嵌套及多任务的锁嵌套,可以继续进行,否则退出关闭中断函数跳出
2、运行OS_SchedNew()函数,查找最高优先级的已经就绪的任务。
假如就绪组中已经置位的最低位是x位,相应的就绪表数组[x]中的数据已经置位的最低位是y位,那么最高优先级z=(x>>8)+y,也就是组号*组容量+组内偏移。目标是在找到x和y。就绪组从取值上来说,最大范围是0~256;就绪表数组中的每一个数据取值范围也是0~256,我们的目标是找到这两个数据中的最低位是哪一位?代入x和y,就能求出最高优先级。
所以:OSUnMapTbl[256]是一个从0~255共256个数据的,按位从低到高排列,位是1的那个位编号分布。
例如0二进制编码是0000 0000,没有被置位的位,所以位编号分布值为0;
1二进制编码是0000 0001,第0位被置位,所以位编号分布值为0;
2二进制编码是0000 0010,第1位被置位,所以位编号分布值为1;
3二进制编码是0000 0011,从低到高来看,第0位是被置位的,所以位编号分布之为0。这里为什么不考虑前一个1,是因为我们在找最高优先级,也就是低位的‘1’
4二进制编码是0000 0100,第2位被置位,所以位编号分布值为2;
以此类推
可以得知上述的x=OSUnMapTbl[OSRdyGrp],y=OSUnMapTbl[OSUnMapTbl[OSRdyGrp]]。//这个应该理解吧。就是查表的做法
1、优先级大于64的话,OSTCBBitY可能达到16位,超过0X0100,x需要单独加8,组号就从8开始了
2、OSTCBY到OSTCBBitY的转换,将1左移OSTCBY位,得到了OSTCBitY。
2、当最高优先级等于当前任务优先级,则退出;否则,将具备最高优先级的任务赋值最高优先级任务控制块指针,计数器+1,执行OS_TASK_SW() OSCtxSw(),该函数是激活一个PendSV中断,在该中断服务例程中实现了寄存器保存及任务切换