CooCox 1.1.4 on mbed with simple blinky example

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers task.c Source File

task.c

Go to the documentation of this file.
00001 /**
00002  *******************************************************************************
00003  * @file       task.c
00004  * @version    V1.1.4    
00005  * @date       2011.04.20
00006  * @brief      task management implementation code of CooCox CoOS kernel.    
00007  *******************************************************************************
00008  * @copy
00009  *
00010  * INTERNAL FILE,DON'T PUBLIC.
00011  * 
00012  * <h2><center>&copy; COPYRIGHT 2009 CooCox </center></h2>
00013  *******************************************************************************
00014  */ 
00015 
00016 
00017 /*---------------------------- Include ---------------------------------------*/
00018 #include <coocox.h>
00019 
00020 /*---------------------------- Variable Define -------------------------------*/
00021 
00022 /*!< Table use to save TCB pointer.              */
00023 OSTCB    TCBTbl [CFG_MAX_USER_TASKS+SYS_TASK_NUM] = {{0}};
00024 
00025 /*!< The stack of IDLE task.                     */
00026 OS_STK   idle_stk[CFG_IDLE_STACK_SIZE] = {0};
00027 
00028 P_OSTCB  FreeTCB      = 0;  /*!< pointer to free TCB                        */
00029 P_OSTCB  TCBRdy       = 0;  /*!< Pointer to the READY list.                 */
00030 P_OSTCB  TCBNext      = 0;  /*!< Poniter to task that next scheduled by OS  */
00031 P_OSTCB  TCBRunning   = 0;  /*!< Pointer to TCB that current running task.  */
00032 U64      OSCheckTime  = 0;     /*!< The counter of system tick.                */
00033 
00034 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00035 OS_TID   PriNum;
00036 U8       ActivePri[CFG_MAX_USER_TASKS+SYS_TASK_NUM];
00037 U8       TaskNumPerPri[CFG_MAX_USER_TASKS+SYS_TASK_NUM];
00038 OS_TID   RdyTaskPri[CFG_MAX_USER_TASKS+SYS_TASK_NUM] = {0};    
00039 U32      RdyTaskPriInfo[(CFG_MAX_USER_TASKS+SYS_TASK_NUM+31)/32];
00040 #endif
00041 
00042 
00043 /**
00044  *******************************************************************************
00045  * @brief      Create a TCB list.      
00046  * @param[in]  None      
00047  * @param[out] None    
00048  * @retval     None         
00049  *
00050  * @par Description
00051  * @details    This function is called by CoOSInit() to initial the empty list     
00052  *             of OS_TCBS,supply a pointer to free TCB.
00053  *******************************************************************************
00054  */
00055 void CreateTCBList(void)
00056 {    
00057     U8  i;
00058     P_OSTCB ptcb1,ptcb2;
00059     
00060 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00061     PriNum = 0;
00062 #endif
00063 
00064     ptcb1 = &TCBTbl[0];                    /* Build the free TCB list            */
00065     ptcb2 = &TCBTbl[1];  
00066     for(i=0;i< (CFG_MAX_USER_TASKS+SYS_TASK_NUM-1);i++ )
00067     {
00068         ptcb1->taskID     = i;
00069         ptcb1->state      = TASK_DORMANT;
00070         ptcb1->TCBnext    = ptcb2;
00071 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00072         RdyTaskPri[i]    = INVALID_ID;
00073         ActivePri[i]     = INVALID_ID;
00074 #endif
00075         ptcb1++;
00076         ptcb2++;    
00077     }
00078 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00079         ActivePri[i]     = INVALID_ID;
00080 #endif
00081 
00082     ptcb1->taskID     = i;    
00083     ptcb1->TCBnext    = 0;
00084     FreeTCB = &TCBTbl[0];         /* Initialize FreeTCB as head item of list  */            
00085 }
00086 
00087 
00088 
00089 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00090 
00091 /**
00092  *******************************************************************************
00093  * @brief      Get sequence number for Assign priority      
00094  * @param[in]  pri            Assign priority     
00095  * @param[out] SequenceNum    priority number 
00096  * @retval     Co_TRUE           Assign priority in priority queue.
00097  *             Co_FALSE          Assign priority not in priority queue.
00098  *                    
00099  * @par Description
00100  * @details    This function is called in Binary-Scheduling Algorithm 
00101  *             to get sequence number for Assign priority.     
00102  *******************************************************************************
00103  */
00104 static BOOL  GetPriSeqNum(U8 pri,OS_TID* SequenceNum)
00105 {
00106     OS_TID  seqNum;
00107     OS_TID  num,tmpNum;
00108     num = 0;
00109     seqNum = PriNum;
00110     while(num != seqNum)
00111     {
00112         tmpNum = num;
00113         num = (num+seqNum)/2;
00114         if(pri == ActivePri[num])
00115         {
00116             *SequenceNum = num;
00117             return Co_TRUE;
00118         }
00119         else if (pri < ActivePri[num])
00120         {
00121             seqNum = num;
00122             num = tmpNum;
00123         }
00124         else
00125         {
00126             num++;
00127         }
00128     }
00129     *SequenceNum = num;
00130     return Co_FALSE;
00131 }
00132 
00133 
00134 /**
00135  *******************************************************************************
00136  * @brief      Get the nearest ready priority sequence number for Assign number      
00137  * @param[in]  seqNum         Assign sequence number     
00138  * @param[out] None
00139  * @retval     INVALID_ID     Cannot find higher ready priority.   
00140  *             Others         Nearest ready priority sequence number          
00141  *                    
00142  * @par Description
00143  * @details    This function is called in Binary-Scheduling Algorithm 
00144  *             to get the nearest ready priority sequence number.    
00145  *******************************************************************************
00146  */
00147 static U8 GetRdyPriSeqNum(U8 seqNum)
00148 {
00149     U32 tmp;
00150     U8  i,j,num;
00151     S8  cnt;
00152     i = seqNum/32;
00153     j = seqNum%32;
00154 
00155     do
00156     {
00157           tmp = RdyTaskPriInfo[i];
00158         if(tmp != 0)
00159         {
00160             num = j/8;
00161             do
00162             {
00163                 if((tmp&(0xff<<(num*8))) !=0 )
00164                 {
00165                     if((tmp&(0xf0<<(num*8))) !=0)
00166                     {
00167                         for(cnt=j; cnt >=(num*8+4); cnt--)    
00168                         {
00169                             if( (tmp&(1<<cnt)) !=0)
00170                             {
00171                                 return (32*i+cnt);
00172                             }    
00173                         }            
00174                     }
00175 
00176                     if((j&0x4)==4)
00177                         j = (j|0x3) -4;
00178                     
00179                     for(cnt=j; cnt >=num*8; cnt--)    
00180                     {
00181                         if( (tmp&(1<<cnt)) !=0)
00182                         {
00183                             return (32*i+cnt);
00184                         }    
00185                     }
00186                 }
00187                 j = num*8 -1;
00188             }while((num--)!=0);
00189         }
00190         j=31;
00191     }while((i--)!=0);
00192     return INVALID_ID;                                            
00193 }
00194 
00195 
00196 /**
00197  *******************************************************************************
00198  * @brief      Remap the ready status of priority queue from Assign sequence number 
00199  * @param[in]  seqNum         Assign sequence number     
00200  * @param[out] None
00201  * @retval     None             
00202  *                    
00203  * @par Description
00204  * @details    This function is called in Binary-Scheduling Algorithm 
00205  *             to Remap the ready status for priority queue.    
00206  *******************************************************************************
00207  */
00208 static void PrioRemap(OS_TID  seqNum)
00209 {
00210     U8 i,j;
00211     U32 tmp;
00212     tmp = j = 0;
00213     j = seqNum/32;
00214     for(i=0;i<seqNum%32;i++)
00215     {
00216         tmp |= 1<<i;
00217     }
00218     tmp &= RdyTaskPriInfo[j];
00219     
00220     for(i=seqNum; i<PriNum; i++)
00221     {
00222         if((i%32==0)&&(i!=seqNum))
00223         {
00224             RdyTaskPriInfo[j++] = tmp;
00225             tmp = 0;
00226         }
00227         if(RdyTaskPri[i] != INVALID_ID)
00228         {
00229             tmp = tmp | (1<<(i%32));
00230         }
00231     }
00232     RdyTaskPriInfo[j++] = tmp;
00233 }
00234 
00235 
00236 /**
00237  *******************************************************************************
00238  * @brief      Get the ready status for assign sequence number 
00239  * @param[in]  seqNum      Assign sequence number     
00240  * @param[out] None
00241  * @retval     Co_TRUE        This priority has ready task
00242  *             Co_FALSE       This priority doesn't have ready task
00243  *                    
00244  * @par Description
00245  * @details    This function is called in Binary-Scheduling Algorithm 
00246  *             to get the ready status for assign sequence number.    
00247  *******************************************************************************
00248  */
00249 static BOOL GetPrioSeqNumStatus(U8 seqNum)
00250 {
00251     if( (RdyTaskPriInfo[seqNum/32] & (1<<(seqNum%32))) == 0)
00252     {
00253         return Co_FALSE;
00254     }
00255     return Co_TRUE;
00256 }
00257 
00258 
00259 /**
00260  *******************************************************************************
00261  * @brief      Set the ready status for assign sequence number 
00262  * @param[in]  seqNum      Assign sequence number
00263  * @param[in]  isRdy       Ready statues for assign sequence number      
00264  * @param[out] None
00265  * @retval     None          
00266  *                    
00267  * @par Description
00268  * @details    This function is called in Binary-Scheduling Algorithm 
00269  *             to set the ready status for assign sequence number.    
00270  *******************************************************************************
00271  */
00272 static void SetPrioSeqNumStatus(U8 seqNum, BOOL isRdy)
00273 {
00274     U32 tmp;
00275     tmp = RdyTaskPriInfo[seqNum/32];
00276     tmp    &= ~(1<<(seqNum%32));
00277     tmp |= isRdy<<(seqNum%32);
00278     RdyTaskPriInfo[seqNum/32] = tmp;
00279 }
00280 
00281 
00282 /**
00283  *******************************************************************************
00284  * @brief      Active priority in queue 
00285  * @param[in]  pri       Task priority
00286  * @param[in]  None     
00287  * @param[out] None
00288  * @retval     None          
00289  *                    
00290  * @par Description
00291  * @details    This function is called in Binary-Scheduling Algorithm 
00292  *             to active priority in queue, if this priority had been in activation,
00293  *             increate the task num for this priority.    
00294  *******************************************************************************
00295  */
00296 void ActiveTaskPri(U8 pri)
00297 {
00298     OS_TID  seqNum,num;
00299     if(GetPriSeqNum(pri,&seqNum) == Co_FALSE)
00300     {
00301         for(num=PriNum;num>seqNum;num--)
00302         {
00303             ActivePri[num]     = ActivePri[num-1];
00304             TaskNumPerPri[num] = TaskNumPerPri[num-1];
00305             RdyTaskPri[num]    = RdyTaskPri[num-1];
00306         }
00307         ActivePri[seqNum]     = pri;
00308         TaskNumPerPri[seqNum] = 1;
00309         RdyTaskPri[seqNum]    = INVALID_ID;
00310         PriNum++;
00311         PrioRemap(seqNum);
00312     }
00313     else
00314     {
00315          TaskNumPerPri[seqNum]++;
00316     }
00317 }
00318 
00319 
00320 
00321 /**
00322  *******************************************************************************
00323  * @brief      Delete priority in queue 
00324  * @param[in]  pri       Task priority
00325  * @param[in]  None     
00326  * @param[out] None
00327  * @retval     None          
00328  *                    
00329  * @par Description
00330  * @details    This function is called in Binary-Scheduling Algorithm 
00331  *             to decrease the task num for this priority, if the num goto 0,
00332  *             remove the priority for queue.
00333  *******************************************************************************
00334  */
00335 void DeleteTaskPri(U8 pri)
00336 {
00337     OS_TID  seqNum,num;
00338 
00339     GetPriSeqNum(pri,&seqNum);
00340     TaskNumPerPri[seqNum]--;
00341     if(TaskNumPerPri[seqNum]==0)
00342     {
00343         for(num=seqNum; num<(PriNum-1); num++)
00344         {
00345             ActivePri[num]     = ActivePri[num+1];
00346             TaskNumPerPri[num] = TaskNumPerPri[num+1];
00347             RdyTaskPri[num]    = RdyTaskPri[num+1];
00348         }
00349         PriNum--;
00350         PrioRemap(seqNum);
00351     }
00352 }
00353 
00354 #endif
00355 
00356 
00357 /**
00358  *******************************************************************************
00359  * @brief      Insert a task to the ready list       
00360  * @param[in]  tcbInsert    A pointer to task will be inserted.
00361  * @param[out] None  
00362  * @retval     None     
00363  *
00364  * @par Description
00365  * @details   This function is called to insert a task to the READY list. 
00366  *******************************************************************************
00367  */
00368 void InsertToTCBRdyList(P_OSTCB tcbInsert)
00369 {
00370     P_OSTCB ptcbNext,ptcb;
00371     U8  prio;
00372 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00373     U8  seqNum;
00374     U8  RdyTaskSeqNum;
00375 #endif
00376     
00377     prio = tcbInsert->prio ;             /* Get PRI of inserted task           */
00378     tcbInsert->state      = TASK_READY;  /* Set task as TASK_READY             */
00379 
00380 #if CFG_ROBIN_EN >0
00381     ptcb = TCBRunning ;
00382     /* Set schedule time for the same PRI task as TCBRunning.                 */
00383     if(prio == ptcb->prio )  /* Is PRI of inserted task equal to running task? */
00384     {
00385         if(ptcb != tcbInsert) /* Yes,is inserted task equal to running task?  */
00386         {
00387             if(ptcb != Co_NULL)            /* No,TCBRunning == Co_NULL?             */
00388             {                           /* N0,OSCheckTime < OSTickCnt?        */
00389                 if(OSCheckTime  < OSTickCnt )     
00390                 {                       /* Yes,set OSCheckTime for task robin */
00391                     OSCheckTime  = OSTickCnt  + ptcb->timeSlice ;    
00392                 }            
00393             }            
00394         }
00395     }
00396 #endif
00397 
00398 
00399 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00400     GetPriSeqNum(prio,&seqNum);
00401     if(GetPrioSeqNumStatus(seqNum) == Co_TRUE)
00402     {
00403         ptcb = &TCBTbl[RdyTaskPri[seqNum]];
00404         RdyTaskPri[seqNum] = tcbInsert->taskID ;
00405     }
00406     else
00407     {
00408         RdyTaskPri[seqNum] = tcbInsert->taskID ;
00409         RdyTaskSeqNum = GetRdyPriSeqNum(seqNum);
00410         SetPrioSeqNumStatus(seqNum, 1);
00411         if(RdyTaskSeqNum == INVALID_ID)
00412         {
00413             ptcb = TCBRdy ;
00414             TaskSchedReq = Co_TRUE;
00415             if(ptcb == Co_NULL)
00416             {
00417                 TCBRdy   = tcbInsert;    
00418             }
00419             else
00420             {
00421                 tcbInsert->TCBnext  = ptcb;  /* Yes,set tcbInsert as head item of list */
00422                 ptcb->TCBprev  = tcbInsert;
00423                 TCBRdy         = tcbInsert;
00424             }
00425             return;
00426         }
00427         else
00428         {
00429             ptcb = &TCBTbl[RdyTaskPri[RdyTaskSeqNum]];    
00430         }
00431     }
00432 
00433     ptcbNext = ptcb->TCBnext ;
00434     tcbInsert->TCBnext  = ptcbNext;    /* Set link for list                  */
00435     ptcb->TCBnext       = tcbInsert;
00436     tcbInsert->TCBprev  = ptcb;
00437     if(ptcbNext != Co_NULL)
00438     {
00439         ptcbNext->TCBprev   = tcbInsert;
00440     }
00441 
00442 
00443 #else
00444     ptcb = TCBRdy ;
00445     if (ptcb == Co_NULL)                   /* Is ready list Co_NULL?                */
00446     {
00447         TaskSchedReq = Co_TRUE;
00448         TCBRdy = tcbInsert;         /* Yse,set tcbInsert as head item of list */
00449     }
00450     else if (prio < ptcb->prio)/* Is PRI of inserted task higher than TCBRdy? */
00451     {
00452         TaskSchedReq = Co_TRUE;
00453         tcbInsert->TCBnext  = ptcb;  /* Yes,set tcbInsert as head item of list */
00454         ptcb->TCBprev   = tcbInsert;
00455         TCBRdy         = tcbInsert;
00456     }
00457     else                                /* No,find correct place              */
00458     {                                    
00459         ptcbNext = ptcb->TCBnext ;       /* Get next item                      */
00460         while(ptcbNext != Co_NULL)         /* Is last item in ready list?        */
00461         {                               /* No,find correct place              */
00462             if(prio < ptcbNext->prio)   /* Is correct place?                  */
00463                 break;                  /* Yes,break circulation              */
00464             ptcb     = ptcbNext;        /* Save current item                  */
00465             ptcbNext = ptcbNext->TCBnext ; /* Get next item                    */
00466         }
00467         tcbInsert->TCBnext  = ptcbNext;  /* Set link for list                  */
00468         ptcb->TCBnext       = tcbInsert;
00469         tcbInsert->TCBprev  = ptcb;
00470         if(ptcbNext != Co_NULL)
00471         {
00472             ptcbNext->TCBprev   = tcbInsert;
00473         }        
00474     }
00475 #endif
00476 }
00477 
00478 
00479 
00480 /**
00481  *******************************************************************************
00482  * @brief      Remove a task from the READY list       
00483  * @param[in]  ptcb     A pointer to task which be removed.     
00484  * @param[out] None                  
00485  * @retval     None         
00486  *
00487  * @par Description
00488  * @details    This function is called to remove a task from the READY list.
00489  *******************************************************************************
00490  */
00491 void RemoveFromTCBRdyList(P_OSTCB ptcb)
00492 {
00493 
00494 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00495     U8 prio;
00496     U8 seqNum;
00497     BOOL isChange;
00498     isChange = Co_FALSE;
00499     prio = ptcb->prio ;
00500     GetPriSeqNum(prio,&seqNum);
00501 #endif
00502 
00503     /* Is there only one item in READY list?                                  */
00504     if((ptcb->TCBnext  == Co_NULL) && (ptcb->TCBprev  == Co_NULL) )
00505     {
00506         TCBRdy = 0;                  /* Yes,set READY list as Co_NULL         */
00507 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00508         isChange = Co_TRUE;
00509 #endif
00510     }
00511     else if(ptcb->TCBprev  == 0)      /* Is the first item in READY list?   */
00512     {   
00513         /* Yes,remove task from the list,and reset the head of READY list     */
00514         TCBRdy = ptcb->TCBnext ;            
00515         ptcb->TCBnext    = 0;
00516         TCBRdy->TCBprev  = 0;
00517 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00518         if(TCBRdy->prio  != prio)
00519             isChange = Co_TRUE;
00520         
00521 #endif
00522     }
00523     else if( ptcb->TCBnext  == 0)     /* Is the last item in READY list?    */
00524     {                                   /* Yes,remove task from list          */
00525 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00526         if(ptcb->TCBprev ->prio  != prio)
00527             isChange = Co_TRUE;
00528         else 
00529             RdyTaskPri[seqNum] = ptcb->TCBprev ->taskID ;
00530 #endif
00531         ptcb->TCBprev ->TCBnext  = 0;
00532         ptcb->TCBprev           = 0;
00533     }
00534     else                                /* No, remove task from list          */
00535     {    
00536 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00537         if((ptcb->TCBprev ->prio  != prio) && (ptcb->TCBnext ->prio  != prio))
00538             isChange = Co_TRUE;
00539         else if((ptcb->TCBprev ->prio  == prio) && (ptcb->TCBnext ->prio  != prio))
00540             RdyTaskPri[seqNum] = ptcb->TCBprev ->taskID ;
00541 #endif                                
00542         ptcb->TCBprev ->TCBnext  = ptcb->TCBnext ;
00543         ptcb->TCBnext ->TCBprev  = ptcb->TCBprev ;
00544         ptcb->TCBnext  = 0;
00545         ptcb->TCBprev  = 0;
00546     }
00547 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00548         if(isChange == Co_TRUE)
00549         {
00550             RdyTaskPri[seqNum] = INVALID_ID;
00551             SetPrioSeqNumStatus(seqNum, 0);
00552         }
00553 #endif
00554 }
00555 
00556 
00557 #if CFG_MUTEX_EN > 0
00558 #define CFG_PRIORITY_SET_EN       (1)
00559 #endif
00560 #if CFG_PRIORITY_SET_EN >0
00561 /**
00562  *******************************************************************************
00563  * @brief      Change task priority       
00564  * @param[in]  taskID     Specify task id.
00565  * @param[in]  priority   New priority.     
00566  * @param[out] None           
00567  * @retval     E_OK              Change priority successful.
00568  * @retval     E_INVALID_ID      Invalid id,change priority fail.
00569  * @retval     E_PROTECTED_TASK  Can't change idle task priority.         
00570  *
00571  * @par Description
00572  * @details    This function is called to change priority for a specify task.     
00573  *******************************************************************************
00574  */
00575 StatusType CoSetPriority(OS_TID taskID,U8 priority)
00576 {            
00577     P_OSTCB ptcb;
00578 #if CFG_MUTEX_EN >0
00579     U8 prio;
00580     P_MUTEX    pMutex;
00581 #endif
00582 #if CFG_EVENT_EN >0
00583     P_ECB pecb;
00584 #endif
00585 
00586     if(taskID == 0)                     /* Is idle task?                      */
00587     {                                             
00588         return E_PROTECTED_TASK;        /* Yes,error return                   */
00589     }   
00590     
00591 #if CFG_PAR_CHECKOUT_EN >0              /* Check validity of parameter        */
00592     if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
00593     {
00594         return E_INVALID_ID;
00595     }
00596 #endif
00597     ptcb = &TCBTbl[taskID];             /* Get TCB of task ID                 */
00598 #if CFG_PAR_CHECKOUT_EN >0    
00599     if(ptcb->state  == TASK_DORMANT)
00600     {
00601         return E_INVALID_ID;
00602     }
00603     if(priority > CFG_LOWEST_PRIO)
00604     {
00605         return E_INVALID_ID;
00606     }
00607 #endif
00608 
00609     if(ptcb->prio  != priority)          /* Is PRI equal to original PRI?      */
00610     {                                   /* No                                 */
00611 #if CFG_MUTEX_EN >0
00612         if(ptcb->mutexID  != INVALID_ID)
00613         {
00614             pMutex = &MutexTbl [ptcb->mutexID ];
00615             if(pMutex->taskID  == ptcb->taskID )  /* Task hold mutex?               */
00616             {
00617                  pMutex->originalPrio = priority;/* Yes,change original PRI in mutex*/
00618                  if(ptcb->prio  < priority)     /* Is task priority higher than set?*/
00619                  {
00620                      return E_OK;                /* Yes,do nothing,return OK       */
00621                  }
00622             }        
00623          }
00624 
00625 #endif    
00626 
00627 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00628         DeleteTaskPri(ptcb->prio );
00629         ActiveTaskPri(priority);    
00630 #endif    
00631 
00632         ptcb->prio  = priority;              /* Change task PRI                */
00633         if(ptcb->state  == TASK_READY)       /* Is task in READY list?         */
00634         {
00635             OsSchedLock();                  /* Yes,reorder task in READY list */
00636             RemoveFromTCBRdyList(ptcb);
00637             InsertToTCBRdyList(ptcb);    
00638             OsSchedUnlock();
00639         }
00640         else if(ptcb->state  == TASK_RUNNING)/* Is task running?               */
00641         {
00642             if(ptcb->prio  > TCBRdy->prio )   /* Yes,Is PRI higher than TCBRdy? */
00643             {
00644                 OsSchedLock();              /* Yes,reorder task in READY list */
00645                 TaskSchedReq = Co_TRUE;
00646                 OsSchedUnlock();
00647             }
00648         }
00649         else
00650         {                                   /* No,task in WAITING list        */
00651 #if CFG_MUTEX_EN >0
00652             if(ptcb->mutexID  != INVALID_ID) /* Is task in mutex WAITING list? */
00653             {
00654                 /* Yes,reset the highest PRI in the list */
00655                 OsSchedLock(); 
00656                 pMutex = &MutexTbl [ptcb->mutexID ];
00657                 ptcb = pMutex->waittingList ;  
00658                 prio = pMutex->originalPrio ; 
00659                 pMutex->hipriTaskID  = pMutex->taskID ;
00660                 while(ptcb != Co_NULL)
00661                 {
00662                     if(ptcb->prio  < prio)
00663                     {
00664                         prio = ptcb->prio ;
00665                         pMutex->hipriTaskID  = ptcb->taskID ;
00666                     }
00667                     ptcb = ptcb->TCBnext ;            
00668                 }
00669                 OsSchedUnlock();
00670                 if(pMutex->originalPrio  != prio)
00671                 {
00672                     CoSetPriority(pMutex->taskID ,prio);    
00673                 }    
00674             }
00675 #endif
00676 
00677 #if CFG_EVENT_EN >0
00678             ptcb = &TCBTbl[taskID];
00679             if(ptcb->eventID  != INVALID_ID) /* Is task in event WAITING list? */
00680             {                                    
00681                 pecb = &EventTbl [ptcb->eventID ];
00682                 
00683                 /* Yes,is event sort type as preemptive PRI?                  */
00684                 if(pecb->eventSortType  == EVENT_SORT_TYPE_PRIO)
00685                 {      
00686                     /* Yes,reorder task in the list                           */
00687                     RemoveEventWaittingList(ptcb);
00688                     EventTaskToWait(pecb,ptcb);
00689                 }    
00690             }
00691 #endif
00692         }
00693     }
00694     return E_OK;
00695 }
00696 #endif
00697 
00698 /**
00699  *******************************************************************************
00700  * @brief      Schedule function      
00701  * @param[in]  None      
00702  * @param[out] None       
00703  * @retval     None     
00704  *
00705  * @par Description
00706  * @details    This function is called by every where need to switch context,
00707  *             It is schedule function of OS kernel.
00708  *******************************************************************************
00709  */
00710 void Schedule(void)
00711 {
00712     U8  RunPrio,RdyPrio;
00713     P_OSTCB pRdyTcb,pCurTcb;
00714    
00715     
00716     pCurTcb = TCBRunning ;    
00717     pRdyTcb = TCBRdy ;
00718 
00719     if((pRdyTcb==Co_NULL) || (pCurTcb != TCBNext) || (OSSchedLock  >1) || (OSIntNesting  >0))
00720     {
00721         return;
00722     }
00723     
00724     TaskSchedReq = Co_FALSE;
00725     RunPrio = pCurTcb->prio ;
00726     RdyPrio = pRdyTcb->prio ;
00727 
00728     /* Is Running task status was changed? */
00729     if(pCurTcb->state  != TASK_RUNNING)    
00730     {
00731         TCBNext        = pRdyTcb;   /* Yes,set TCBNext and reorder READY list */
00732         pRdyTcb->state  = TASK_RUNNING;
00733         RemoveFromTCBRdyList(pRdyTcb);
00734     }
00735 
00736     else if(RdyPrio < RunPrio )     /* Is higher PRI task coming in?          */
00737     {
00738         TCBNext        = pRdyTcb;   /* Yes,set TCBNext and reorder READY list */
00739         InsertToTCBRdyList(pCurTcb);
00740         RemoveFromTCBRdyList(pRdyTcb);
00741         pRdyTcb->state  = TASK_RUNNING;
00742     }
00743     
00744 #if CFG_ROBIN_EN >0                 /* Is time for robinning                  */                            
00745     else if((RunPrio == RdyPrio) && (OSCheckTime  == OSTickCnt ))
00746     {
00747         TCBNext        = pRdyTcb;   /* Yes,set TCBNext and reorder READY list */
00748         InsertToTCBRdyList(pCurTcb);
00749         RemoveFromTCBRdyList(pRdyTcb);
00750         pRdyTcb->state  = TASK_RUNNING;
00751     }
00752 #endif
00753     else
00754     {                                    
00755         return;    
00756     }
00757     
00758 #if CFG_ROBIN_EN >0
00759     if(TCBNext->prio  == TCBRdy->prio )  /* Reset OSCheckTime for task robinnig */
00760         OSCheckTime  = OSTickCnt  + TCBNext->timeSlice ;
00761 #endif
00762     
00763   
00764 #if CFG_STK_CHECKOUT_EN > 0                       /* Is stack overflow?       */
00765     if((pCurTcb->stkPtr  < pCurTcb->stack )||(*(U32*)(pCurTcb->stack ) != MAGIC_WORD))       
00766     {                                    
00767         CoStkOverflowHook(pCurTcb->taskID );       /* Yes,call handler         */        
00768     }   
00769 #endif
00770      
00771     SwitchContext();                              /* Call task context switch */
00772 }
00773 
00774 
00775 /**
00776  *******************************************************************************
00777  * @brief      Assign a TCB to task being created                         
00778  * @param[in]  None     
00779  * @param[out] None     
00780  *      
00781  * @retval     XXXX                             
00782  *
00783  * @par Description
00784  * @details    This function is called to assign a task control block for task 
00785  *              being created.
00786  *******************************************************************************
00787  */
00788 static P_OSTCB AssignTCB(void)
00789 {
00790     P_OSTCB    ptcb;
00791     
00792     OsSchedLock();                      /* Lock schedule                      */
00793     if(FreeTCB == 0)                 /* Is there no free TCB               */
00794     {
00795         OsSchedUnlock();                /* Yes,unlock schedule                */
00796         return 0;                    /* Error return                       */
00797     }    
00798     ptcb    = FreeTCB ;          /* Yes,assgin free TCB for this task  */    
00799     /* Set next item as the head of free TCB list                     */
00800     FreeTCB = FreeTCB->TCBnext ; 
00801     OsSchedUnlock();
00802     return ptcb;
00803 }
00804 
00805 
00806 /**
00807  *******************************************************************************
00808  * @brief      Create a task       
00809  * @param[in]  task       Task code entry.
00810  * @param[in]  argv       The parameter passed to task.
00811  * @param[in]  parameter  Task priority + stack size + time slice + isWaitting.
00812  * @param[in]  stk        Pointer to stack top of task.
00813  * @param[out] None   
00814  * @retval     E_CREATE_FAIL    Fail to create a task .
00815  * @retval     others           Valid task id.                 
00816  *
00817  * @par Description
00818  * @details    This function is called by application to create a task,return a id 
00819  *             to mark this task.
00820  *******************************************************************************
00821  */
00822 OS_TID CreateTask(FUNCPtr task,void *argv,U32 parameter,OS_STK *stk)
00823 {
00824     OS_STK* stkTopPtr;
00825     P_OSTCB ptcb;
00826     U8      prio;
00827 #if CFG_ROBIN_EN >0    
00828     U16     timeSlice;
00829 #endif
00830    
00831 #if CFG_STK_CHECKOUT_EN >0              /* Check validity of parameter        */
00832     U16 sktSz;
00833     sktSz = (parameter&0xfff00)>>8;    
00834 #endif
00835     prio = parameter&0xff;
00836 
00837 #if CFG_PAR_CHECKOUT_EN >0              /* Check validity of parameter        */
00838     if(task == 0)
00839     {
00840         return E_CREATE_FAIL;
00841     }
00842     if(stk == 0)
00843     {
00844         return E_CREATE_FAIL;
00845     }
00846     if(prio > CFG_LOWEST_PRIO)
00847     {
00848         return E_CREATE_FAIL;        
00849     }
00850 #if CFG_STK_CHECKOUT_EN >0
00851     if(sktSz < 20)
00852     {
00853         return E_CREATE_FAIL;        
00854     }
00855 #endif      // CFG_STK_CHECKOUT_EN
00856 #endif      // CFG_PAR_CHECKOUT_EN
00857 
00858 #if CFG_TASK_SCHEDULE_EN == 0
00859     if(TCBRunning != 0)
00860          return E_CREATE_FAIL;    
00861 #endif   
00862 
00863     stkTopPtr = InitTaskContext(task,argv,stk);   /* Initialize task context. */
00864     
00865     ptcb = AssignTCB();                 /* Get free TCB to use                */
00866     
00867     if(ptcb == 0)                    /* Is free TCB equal to Co_NULL?         */
00868     {
00869         return E_CREATE_FAIL;           /* Yes,error return                   */
00870     }
00871     
00872     ptcb->stkPtr  = stkTopPtr;           /* Initialize TCB as user set         */
00873     ptcb->prio    = prio;
00874 #if CFG_STK_CHECKOUT_EN >0
00875     ptcb->stack  = stk+1 - sktSz; /* Set bottom stack for stack overflow check */
00876     *(U32*)(ptcb->stack ) = MAGIC_WORD;
00877 #endif    
00878 
00879 #if CFG_TASK_WAITTING_EN >0
00880     ptcb->delayTick     = INVALID_VALUE;    
00881 #endif         
00882 
00883 #if CFG_TASK_SCHEDULE_EN == 0
00884     ptcb->taskFuc = task;
00885     ptcb->taskStk = stk;
00886 #endif     
00887     ptcb->TCBnext  = 0;               /* Initialize TCB link in READY list  */
00888     ptcb->TCBprev  = 0;
00889 
00890 #if CFG_ROBIN_EN >0                        /* Set task time slice for task robin */
00891     timeSlice = (parameter&0x7fff0000)>>20; 
00892     if(timeSlice == 0)
00893     {
00894         timeSlice = CFG_TIME_SLICE;
00895     }
00896     ptcb->timeSlice  = timeSlice;
00897 #endif
00898 
00899 #if CFG_FLAG_EN > 0
00900     ptcb->pnode  = 0;                 /* Initialize task as no flag waiting */
00901 #endif
00902 
00903 #if CFG_EVENT_EN > 0
00904     ptcb->eventID   = INVALID_ID;          /* Initialize task as no event waiting*/
00905     ptcb->pmail     = 0;
00906     ptcb->waitNext  = 0;
00907     ptcb->waitPrev  = 0;
00908 #endif
00909 
00910 #if CFG_MUTEX_EN > 0
00911     /* Initialize task as no mutex holding or waiting                         */
00912     ptcb->mutexID  = INVALID_ID; 
00913 #endif 
00914 
00915 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00916     ActiveTaskPri(prio);    
00917 #endif    
00918 
00919     if((parameter>>31) == 0)            /* Is task in waitting state?         */
00920     {                                    /* No,set it into ready list          */
00921         OsSchedLock();                  /* Lock schedule                      */
00922         InsertToTCBRdyList(ptcb);       /* Insert into the READY list         */
00923         OsSchedUnlock();                /* Unlock schedule                    */
00924     }
00925     else
00926     {                                    /* Yes,Set task status as TASK_WAITING*/
00927         ptcb->state    = TASK_WAITING;    
00928     }
00929     return ptcb->taskID ;                /* Return task ID                     */
00930 }
00931 
00932 
00933 /**
00934  *******************************************************************************
00935  * @brief      Delete Task     
00936  * @param[in]  taskID      Task ID 
00937  * @param[out] None  
00938  * @retval     E_INVALID_ID      Invalid task ID.     
00939  * @retval     E_PROTECTED_TASK  Protected task in OS.     
00940  * @retval     E_OK              Delete successful.    
00941  *
00942  * @par Description
00943  * @details    This function is called to delete assign task.     
00944  *******************************************************************************
00945  */
00946 StatusType CoDelTask(OS_TID taskID)
00947 {
00948     P_OSTCB ptcb;
00949 
00950 #if CFG_PAR_CHECKOUT_EN >0              /* Check validity of parameter        */
00951     if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
00952     {
00953         return E_INVALID_ID;
00954     }
00955 #endif
00956     ptcb = &TCBTbl[taskID];
00957 #if CFG_PAR_CHECKOUT_EN >0 
00958     if(ptcb->state  == TASK_DORMANT)
00959     {
00960         return E_INVALID_ID;
00961     }
00962 #endif
00963     if(taskID == 0)                     /* Is idle task?                      */
00964     {                                             
00965         return E_PROTECTED_TASK;        /* Yes,error return                   */
00966     }    
00967     
00968     if(ptcb->state  == TASK_RUNNING)     /* Is task running?                   */
00969     {
00970         if(OSSchedLock  != 0)            /* Yes,is OS lock?                    */
00971         {
00972             return E_OS_IN_LOCK;        /* Yes,error return                   */
00973         }    
00974     }
00975         
00976 #if CFG_MUTEX_EN >0                     /* Do task hold mutex?                */
00977     if(ptcb->mutexID  != INVALID_ID)
00978     {
00979         if(MutexTbl [ptcb->mutexID ].taskID  == ptcb->taskID )
00980         {                               /* Yes,leave the mutex                */
00981             CoLeaveMutexSection(ptcb->mutexID );
00982         }
00983     }
00984     
00985 #endif    
00986 
00987     OsSchedLock();                      /* Lock schedule                      */
00988     
00989     if(ptcb->state  == TASK_READY)       /* Is task in READY list?             */
00990     {
00991         RemoveFromTCBRdyList(ptcb);     /* Yes,remove task from the READY list*/
00992     }
00993 
00994 #if CFG_TASK_WAITTING_EN > 0 
00995     else if(ptcb->state  == TASK_WAITING)/* Is task in the WAITING list?       */
00996     {
00997         /* Yes,Is task in delay list? */
00998         if(ptcb->delayTick  != INVALID_VALUE)                     
00999         {
01000             RemoveDelayList(ptcb);      /* Yes,remove task from READY list    */
01001         }
01002 
01003 #if CFG_EVENT_EN > 0
01004         if(ptcb->eventID  != INVALID_ID) /* Is task in event waiting list?     */
01005         {        
01006             /* Yes,remove task from event waiting list                        */
01007             RemoveEventWaittingList(ptcb);    
01008         }
01009 #endif
01010 
01011 #if CFG_FLAG_EN > 0
01012         if(ptcb->pnode  != 0)         /* Is task in flag waiting list?      */
01013         {
01014             /* Yes,remove task from flag waiting list                         */
01015             RemoveLinkNode((P_FLAG_NODE)ptcb->pnode );    
01016         }
01017 #endif
01018 
01019 #if CFG_MUTEX_EN >0
01020         if(ptcb->mutexID  != INVALID_ID) /* Is task in mutex waiting list?     */
01021         {
01022             RemoveMutexList(ptcb);  /* Yes,remove task from mutex waiting list*/
01023         }
01024 #endif
01025       }
01026 #endif
01027     ptcb->state    = TASK_DORMANT;       /* Release TCB                        */
01028     TaskSchedReq  = Co_TRUE;
01029 
01030 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
01031     DeleteTaskPri(ptcb->prio );    
01032 #endif    
01033 
01034 #if CFG_TASK_SCHEDULE_EN >0
01035     ptcb->TCBnext  = FreeTCB ;
01036     FreeTCB       = ptcb;
01037 #endif
01038     OsSchedUnlock();                    /* Unlock schedule                    */
01039     return E_OK;                        /* return OK                          */
01040 }
01041 
01042 
01043 /**
01044  *******************************************************************************
01045  * @brief      Exit Task       
01046  * @param[in]  None 
01047  * @param[out] None  
01048  * @retval     None             
01049  *
01050  * @par Description
01051  * @details    This function is called to exit current task.     
01052  *******************************************************************************
01053  */
01054 void CoExitTask(void)
01055 {
01056     CoDelTask(TCBRunning->taskID );      /* Call task delete function          */
01057 }
01058 
01059 
01060 #if CFG_TASK_SCHEDULE_EN ==0
01061 /**
01062  *******************************************************************************
01063  * @brief      Activate Task       
01064  * @param[in]  taskID      Task ID 
01065  * @param[in]  argv        Task argv 
01066  * @param[out] None  
01067  * @retval     E_INVALID_ID      Invalid task ID.      
01068  * @retval     E_OK              Activate task successful.             
01069  *
01070  * @par Description
01071  * @details    This function is called to activate current task.     
01072  *******************************************************************************
01073  */
01074 StatusType CoActivateTask(OS_TID taskID,void *argv)
01075 {
01076     P_OSTCB ptcb;
01077     OS_STK* stkTopPtr;
01078 #if CFG_PAR_CHECKOUT_EN >0              /* Check validity of parameter        */
01079     if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
01080     {
01081         return E_INVALID_ID;
01082     }
01083 #endif
01084     ptcb = &TCBTbl[taskID];
01085 #if CFG_PAR_CHECKOUT_EN >0
01086     if(ptcb->stkPtr  == Co_NULL)
01087         return E_INVALID_ID;
01088 #endif
01089     if(ptcb->state  != TASK_DORMANT)    
01090         return E_OK;
01091 
01092 
01093                                         /* Initialize task context. */
01094     stkTopPtr = InitTaskContext(ptcb->taskFuc,argv,ptcb->taskStk);   
01095         
01096     ptcb->stkPtr  = stkTopPtr;           /* Initialize TCB as user set         */
01097     OsSchedLock();                      /* Lock schedule                      */
01098     InsertToTCBRdyList(ptcb);           /* Insert into the READY list         */
01099     OsSchedUnlock();                    /* Unlock schedule                    */
01100     return E_OK;
01101 }
01102 #endif
01103 
01104 
01105 /**
01106  *******************************************************************************
01107  * @brief      Get current task id      
01108  * @param[in]  None
01109  * @param[out] None
01110  * @retval     ID of the current task.             
01111  *
01112  * @par Description
01113  * @details    This function is called to get current task id.     
01114  *******************************************************************************
01115  */
01116 OS_TID CoGetCurTaskID(void)
01117 {
01118     return (TCBRunning->taskID );        /* Return running task ID             */
01119 }
01120 
01121 #if CFG_TASK_SUSPEND_EN >0
01122 /**
01123  *******************************************************************************
01124  * @brief      Suspend Task      
01125  * @param[in]  taskID    ID of task that want to suspend.
01126  * @param[out] None  
01127  * @retval     E_OK                  Task suspend successful. 
01128  * @retval     E_INVALID_ID          Invalid event ID. 
01129  * @retval     E_PROTECTED_TASK      Can't suspend idle task. 
01130  * @retval     E_ALREADY_IN_WAITING  Task now in waiting state.
01131       
01132  *
01133  * @par Description
01134  * @details    This function is called to exit current task.     
01135  *******************************************************************************
01136  */
01137 StatusType CoSuspendTask(OS_TID taskID)
01138 {
01139     P_OSTCB ptcb;
01140 
01141     if(taskID == 0)                     /* Is idle task?                      */
01142     {                                             
01143         return E_PROTECTED_TASK;        /* Yes,error return                   */
01144     }   
01145 #if CFG_PAR_CHECKOUT_EN >0              /* Check validity of parameter        */
01146     if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
01147     {
01148         return E_INVALID_ID;
01149     }
01150 #endif
01151     ptcb = &TCBTbl[taskID];
01152 #if CFG_PAR_CHECKOUT_EN >0  
01153     if(ptcb->state  == TASK_DORMANT)
01154     {
01155         return E_INVALID_ID;
01156     }
01157 #endif
01158     if(OSSchedLock  != 0)
01159     {
01160         return E_OS_IN_LOCK;
01161     }
01162     if(ptcb->state  == TASK_WAITING)     /* Is task in WAITING list?           */
01163     {
01164         return E_ALREADY_IN_WAITING;    /* Yes,error return                   */
01165     }
01166     
01167     OsSchedLock();    
01168     if(ptcb != TCBRunning)              /* Is runing task?                    */
01169     {
01170         RemoveFromTCBRdyList(ptcb);     /* No,Remove task from READY list     */
01171     }
01172     else
01173     {
01174         TaskSchedReq = Co_TRUE;
01175     }
01176 
01177     ptcb->state  = TASK_WAITING;            /* Set task status as TASK_WAITING    */
01178     OsSchedUnlock();                    /* Call task schedule                 */
01179     return E_OK;                        /* Return OK                          */
01180 }
01181 
01182 
01183 /**
01184  *******************************************************************************
01185  * @brief      Awake Task     
01186  * @param[in]  taskID      ID of task that will been awaked.
01187  * @param[out] None  
01188  * @retval     E_OK                 Task awake successful. 
01189  * @retval     E_INVALID_ID         Invalid task ID.
01190  * @retval     E_TASK_NOT_WAITING   Task now not in waiting state.
01191  * @retval     E_TASK_WAIT_OTHER    Task now waiting other awake event.
01192  * @retval     E_PROTECTED_TASK     Idle task mustn't be awaked.      
01193  *
01194  * @par Description
01195  * @details    This function is called to awake current task.     
01196  *******************************************************************************
01197  */
01198 StatusType CoAwakeTask(OS_TID taskID)
01199 {
01200     P_OSTCB ptcb;
01201     
01202      if(taskID == 0)                     /* Is idle task?                      */
01203     {                                             
01204         return E_PROTECTED_TASK;        /* Yes,error return                   */
01205     } 
01206 #if CFG_PAR_CHECKOUT_EN >0              /* Check validity of parameter        */
01207     if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
01208     {
01209         return E_INVALID_ID;
01210     }
01211 #endif
01212     ptcb = &TCBTbl[taskID];
01213 #if CFG_PAR_CHECKOUT_EN >0  
01214     if(ptcb->state  == TASK_DORMANT)
01215     {
01216         return E_INVALID_ID;
01217     }
01218 #endif
01219     
01220     if(ptcb->state  != TASK_WAITING)     /* Is task in WAITING list            */
01221     {
01222         return E_TASK_NOT_WAITING;      /* No,error return                    */
01223     }    
01224 
01225 #if CFG_TASK_WAITTING_EN > 0
01226     if(ptcb->delayTick  != INVALID_VALUE)/* Is task in READY list              */
01227     {
01228         return E_TASK_WAIT_OTHER;       /* Yes,error return                   */
01229     }
01230 
01231 #if CFG_FLAG_EN > 0
01232     if(ptcb->pnode  != Co_NULL)             /* Is task in flag waiting list       */
01233     {
01234         return E_TASK_WAIT_OTHER;       /* Yes,error return                   */
01235     }
01236 #endif
01237 
01238 #if CFG_EVENT_EN>0
01239     if(ptcb->eventID  != INVALID_ID)     /* Is task in event waiting list      */
01240     {
01241         return E_TASK_WAIT_OTHER;       /* Yes,error return                   */
01242     }
01243 #endif    
01244 
01245 #if CFG_MUTEX_EN > 0
01246     if(ptcb->mutexID  != INVALID_ID)     /* Is task in mutex waiting list      */
01247     {
01248         return E_TASK_WAIT_OTHER;       /* Yes,error return                   */
01249     }
01250 #endif
01251 
01252 #endif      //CFG_TASK_WAITTING_EN
01253 
01254     /* All no,so WAITING state was set by CoSuspendTask()                     */
01255     OsSchedLock();                      /* Lock schedule                      */
01256     InsertToTCBRdyList(ptcb);           /* Insert the task into the READY list*/
01257     OsSchedUnlock();                    /* Unlock schedule                    */
01258     return E_OK;                        /* return OK                          */
01259 }
01260 #endif