electronix79
/
CoOS_mbed
CooCox 1.1.4 on mbed with simple blinky example
Embed:
(wiki syntax)
Show/hide line numbers
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>© 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
Generated on Tue Jul 12 2022 18:19:10 by 1.7.2