ucos OS_SchedNew函数

说明:这个函数由ucos的其他服务调用,用来决定即将运行的优先级最高的任务。它改变全局变量OSPrioHighRdy。
 
  参数:无
 
  返回值:无
 
  注意:     这个函数是内部函数,外部应用无法调用。
            这个函数被调用时,中断被假定为关闭。
 
//新版本提供了对256个任务的支持,由 OS_SchedNew函数计算出优先级再交给OS_Sched使用。
//书上的版本是没有这个函数的。
static   void   OS_SchedNew (void)                  
{
#if OS_LOWEST_PRIO <= 63u                 //根据任务数是否大于64采取不同的计算方案
    INT8U   y;                            
    y   = OSUnMapTbl[OSRdyGrp];           // OSUnMapTbl可以理解为一个解码表
    OSPrioHighRdy = (INT8U)((y << 3u) + OSUnMapTbl[OSRdyTbl[y]]);
                                          //OSReadyTbl的大小为【OS_LOWEST_PRIO/8+1】
 
 
#else                                     //任务数大于64时计算优先级的方法                              INT8U     y;
    OS_PRIO   *ptbl;                       //任务数大于64时 *ptbl是指向16位数的指针                        if ((OSRdyGrp & 0xFFu) != 0u)    
    //有任务优先级低于64的函数就绪时那高于64的就不要计算了,算了最高优先级也不是它    
    {    
        y = OSUnMapTbl[OSRdyGrp & 0xFFu];//数字后面加u表示无符号整形 
   
else 
{
        y = OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] + 8u;
    }
    ptbl = &OSRdyTbl[y];  //OSReadyTbl的大小为【OS_LOWEST_PRIO/16+1】与任务数小于64时不同
    if ((*ptbl & 0xFFu) != 0u) 
    {
        OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(*ptbl & 0xFFu)]);
   
    else 
    {
        OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u);
    }
#endif
}
补上详细的计算方法:
                           1.任务数小于64的情况
    先明确几个变量的作用
    1.(u8) OSRdyGrp:每一个bit代表一个组,一共8组,每组管理8个任务(具体哪一个记录在 OSRdyTbl中 )。
    2.(u8) OSPrioHighRdy:格式与 OS_PRIO相同,记录当前最高优先级任务的优先级。
    3.(u8)OS_PRIO:来自  EVENT CONTROL BLOCK(事件控制块)用来记录任务优先级,与优先级一对一关系。
    4.(u8) OSReadyTbl:就绪表啦!按bit排就是下面的样子。
     

      当一个任务就绪时,必须在0SRdyGrp和OSRdyTbl中标记,标记方法如下。

       
      OSRdyGrp|=OSMapTbl[OS_PRIO>>3] //记录组就绪标志    
      //OS_PRIO的yyy有2^3种取法,记录组号TBL[yyy](就绪表第几行)
      OSRdyTbl[prio>>3]|= OSMapTbl[OS_PRIO&0x07] //在TBL[yyy]上记录列就绪标志(在就绪表中写就绪标志)  
      // OS_PRIO&0x07就是XXX。 OSMapTbl[OS_PRIO&0x07]把XXX转换为位掩码
        OSMapTbl数组如下 
      OSMapTbl[8]={00000001,00000010,00000100,00001000,00010000,00100000,01000000,10000000}
      这个数组就是把XXX或YYY转换为上面格式,用来给 OSRdyGrp, TBL[yyy] 特定bit置1。
       
      OS_SchedNew的作用就是依靠0SRdyGrp和OSRdyTbl计算出就绪任务的最高优先级,解码方法如下。
      
       y  = OSUnMapTbl[OSRdyGrp];           
      OSPrioHighRdy = (INT8U)((y << 3u) + OSUnMapTbl[OSRdyTbl[y]]);
      
         OSUnMapTbl[OSRdyGrp]确定最高就绪组Y OSRdyGrp 比如最高就绪组是0组,那么OSRdyGrp的可能是00000001,00000011,00000101,00001001......11111111.一共2^7种。我们通过判断置1的最小就绪位是0位就可以知道最高就绪组为0组。计算机(人视觉的并行处理比计算机强多了 )也要一位一位判断。先看第零位是不是1,是就是第零组,不是判断第2位。那前几位还好说,后面几位的计算量是相当大的。不想算干脆用个已经算好的答案来映射吧。 OSUnMapTbl 就是这样一个 对答案 数组(有效减少计算量)。

        OSUnMapTbl[OSRdyGrp] 的值计算好后保存在Y中, OSRdyTbl[y] 记录的就是最高就绪组中的就绪情况。 OSUnMapTbl[OSRdyTbl[y]] 用答案表算出这组中最高就绪任务X (y << 3u) 这个就是他在第几组,一组8个任务,Y<<3相当于Y*8   OSPrioHighRdy 就等于Y*8+X
      
                                2 .任务数大于64的情况

     任务数大于64时任务就绪表就是16*16=256( OSRdyGrp和 OSRdyTbl 是16位的 ),可以管理256个任务了。
      if ((OSRdyGrp & 0xFFu) != 0u)       //判断优先级前64位的任务是否就绪。
     { y = OSUnMapTbl[OSRdyGrp & 0xFFu];}  // 前128(8*16)个任务最高就绪级的计算方法和情况一是一样的但是 OSPrioHighRdy格式不是00YYYXXX 而是YYYYXXXX 2^4*2^4=256
     else
     { y = OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] + 8u; }
     // OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] 计算后八组加8就是表示前八组都没有就绪。(一共16组)因为还是八组一起判断的所以 OSUnMapTbl可以通用。
     ptbl = &OSRdyTbl[y];                //这里用个指针来代替 OSRdyTbl[y]应该有助于提高计算速度  
      if ((*ptbl & 0xFFu) != 0u) 
      { OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(*ptbl & 0xFFu)]);
      else 
      { OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u); }
     
     OSUnMapTbl[(*ptbl & 0xFFu)])X的前8位就绪
      OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u)X的后八位就绪要加8
      (y << 4u)  就是Y*16 OSPrioHighRdy 就等于Y*16+X
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值