專(zhuān)注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

ucos OS_SchedNew

作者:佚名   來(lái)源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年04月27日   【字體:

  說(shuō)明:這個(gè)函數(shù)由ucos的其他服務(wù)調(diào)用,用來(lái)決定即將運(yùn)行的優(yōu)先級(jí)最高的任務(wù)。它改變?nèi)肿兞縊SPrioHighRdy。

 
  參數(shù):無(wú)
 
  返回值:無(wú)
 
  注意:    這個(gè)函數(shù)是內(nèi)部函數(shù),外部應(yīng)用無(wú)法調(diào)用。
            這個(gè)函數(shù)被調(diào)用時(shí),中斷被假定為關(guān)閉。
 
//新版本提供了對(duì)256個(gè)任務(wù)的支持,由 OS_SchedNew函數(shù)計(jì)算出優(yōu)先級(jí)再交給OS_Sched使用。
//書(shū)上的版本是沒(méi)有這個(gè)函數(shù)的。
static  void  OS_SchedNew (void)                 
{
#if OS_LOWEST_PRIO <= 63u                //根據(jù)任務(wù)數(shù)是否大于64采取不同的計(jì)算方案
    INT8U   y;                            
    y  = OSUnMapTbl[OSRdyGrp];           // OSUnMapTbl可以理解為一個(gè)解碼表
    OSPrioHighRdy = (INT8U)((y << 3u) + OSUnMapTbl[OSRdyTbl[y]]);
                                         //OSReadyTbl的大小為【OS_LOWEST_PRIO/8+1】
 
 
#else                                    //任務(wù)數(shù)大于64時(shí)計(jì)算優(yōu)先級(jí)的方法                              INT8U     y;
    OS_PRIO  *ptbl;                      //任務(wù)數(shù)大于64時(shí) *ptbl是指向16位數(shù)的指針                      if ((OSRdyGrp & 0xFFu) != 0u)   
    //有任務(wù)優(yōu)先級(jí)低于64的函數(shù)就緒時(shí)那高于64的就不要計(jì)算了,算了最高優(yōu)先級(jí)也不是它   
    {   
        y = OSUnMapTbl[OSRdyGrp & 0xFFu];//數(shù)字后面加u表示無(wú)符號(hào)整形 
   
else 
{
        y = OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] + 8u;
    }
    ptbl = &OSRdyTbl[y]; //OSReadyTbl的大小為【OS_LOWEST_PRIO/16+1】與任務(wù)數(shù)小于64時(shí)不同
    if ((*ptbl & 0xFFu) != 0u) 
    {
        OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(*ptbl & 0xFFu)]);
   
    else 
    {
        OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u);
    }
#endif
}
補(bǔ)上詳細(xì)的計(jì)算方法:
                           1.任務(wù)數(shù)小于64的情況
    先明確幾個(gè)變量的作用
    1.(u8)OSRdyGrp:每一個(gè)bit代表一個(gè)組,一共8組,每組管理8個(gè)任務(wù)(具體哪一個(gè)記錄在OSRdyTbl中)。
    2.(u8)OSPrioHighRdy:格式與OS_PRIO相同,記錄當(dāng)前最高優(yōu)先級(jí)任務(wù)的優(yōu)先級(jí)。
    3.(u8)OS_PRIO:來(lái)自 EVENT CONTROL BLOCK(事件控制塊)用來(lái)記錄任務(wù)優(yōu)先級(jí),與優(yōu)先級(jí)一對(duì)一關(guān)系。
    4.(u8)OSReadyTbl:就緒表啦!按bit排就是下面的樣子。
    

      當(dāng)一個(gè)任務(wù)就緒時(shí),必須在0SRdyGrp和OSRdyTbl中標(biāo)記,標(biāo)記方法如下。

      
      OSRdyGrp|=OSMapTbl[OS_PRIO>>3] //記錄組就緒標(biāo)志   
      //OS_PRIO的yyy有2^3種取法,記錄組號(hào)TBL[yyy](就緒表第幾行)
      OSRdyTbl[prio>>3]|= OSMapTbl[OS_PRIO&0x07] //在TBL[yyy]上記錄列就緒標(biāo)志(在就緒表中寫(xiě)就緒標(biāo)志)  
      //OS_PRIO&0x07就是XXX。OSMapTbl[OS_PRIO&0x07]把XXX轉(zhuǎn)換為位掩碼
      OSMapTbl數(shù)組如下 
      OSMapTbl[8]={00000001,00000010,00000100,00001000,00010000,00100000,01000000,10000000}
      這個(gè)數(shù)組就是把XXX或YYY轉(zhuǎn)換為上面格式,用來(lái)給OSRdyGrp,TBL[yyy]特定bit置1。
      
      OS_SchedNew的作用就是依靠0SRdyGrp和OSRdyTbl計(jì)算出就緒任務(wù)的最高優(yōu)先級(jí),解碼方法如下。
      
      y  = OSUnMapTbl[OSRdyGrp];           
      OSPrioHighRdy = (INT8U)((y << 3u) + OSUnMapTbl[OSRdyTbl[y]]);
      
       OSUnMapTbl[OSRdyGrp]確定最高就緒組YOSRdyGrp 比如最高就緒組是0組,那么OSRdyGrp的可能是00000001,00000011,00000101,00001001......11111111.一共2^7種。我們通過(guò)判斷置1的最小就緒位是0位就可以知道最高就緒組為0組。計(jì)算機(jī)(人視覺(jué)的并行處理比計(jì)算機(jī)強(qiáng)多了)也要一位一位判斷。先看第零位是不是1,是就是第零組,不是判斷第2位。那前幾位還好說(shuō),后面幾位的計(jì)算量是相當(dāng)大的。不想算干脆用個(gè)已經(jīng)算好的答案來(lái)映射吧。OSUnMapTbl就是這樣一個(gè)對(duì)答案數(shù)組(有效減少計(jì)算量)。

       OSUnMapTbl[OSRdyGrp]的值計(jì)算好后保存在Y中,OSRdyTbl[y]記錄的就是最高就緒組中的就緒情況。OSUnMapTbl[OSRdyTbl[y]]用答案表算出這組中最高就緒任務(wù)X。(y << 3u)這個(gè)就是他在第幾組,一組8個(gè)任務(wù),Y<<3相當(dāng)于Y*8 OSPrioHighRdy就等于Y*8+X
      
                                2.任務(wù)數(shù)大于64的情況

     任務(wù)數(shù)大于64時(shí)任務(wù)就緒表就是16*16=256(OSRdyGrp和OSRdyTbl是16位的),可以管理256個(gè)任務(wù)了。
     if ((OSRdyGrp & 0xFFu) != 0u)       //判斷優(yōu)先級(jí)前64位的任務(wù)是否就緒。
     {y = OSUnMapTbl[OSRdyGrp & 0xFFu];} //前128(8*16)個(gè)任務(wù)最高就緒級(jí)的計(jì)算方法和情況一是一樣的但是OSPrioHighRdy格式不是00YYYXXX 而是YYYYXXXX 2^4*2^4=256
     else
     {y = OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] + 8u;}
     //OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] 計(jì)算后八組加8就是表示前八組都沒(méi)有就緒。(一共16組)因?yàn)檫是八組一起判斷的所以OSUnMapTbl可以通用。
     ptbl = &OSRdyTbl[y];                //這里用個(gè)指針來(lái)代替OSRdyTbl[y]應(yīng)該有助于提高計(jì)算速度 
     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*16OSPrioHighRdy就等于Y*16+X
 
關(guān)閉窗口

相關(guān)文章