時鐘節拍中斷呼叫OSTimeTick()函式
void OSTimeTick (void)
{
if (OSRunning != OS_STATE_OS_RUNNING) {
return;
}
> OSTimeTickHook(); /* Call user definable hook */
#if (OS_CFG_SCHED_ROUND_ROBIN_EN > 0u)
OS_SchedRoundRobin(&OSRdyList[OSPrioCur]); /* Update quanta ctr for the task which just ran */
#endif
#if (OS_CFG_TICK_EN > 0u)
OS_TickUpdate(1u); /* Update from the ISR */
#endif
}
1.呼叫自定義函式
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void OSTimeTickHook (void) { #if OS_CFG_APP_HOOKS_EN > 0u if (OS_AppTimeTickHookPtr != (OS_APP_HOOK_VOID)0) { (*OS_AppTimeTickHookPtr)(); } #endif }
2.時間片排程
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#if (OS_CFG_SCHED_ROUND_ROBIN_EN > 0u) void OS_SchedRoundRobin (OS_RDY_LIST *p_rdy_list) { OS_TCB *p_tcb; CPU_SR_ALLOC(); if (OSSchedRoundRobinEn != OS_TRUE) { /* Make sure round-robin has been enabled */ return; } CPU_CRITICAL_ENTER(); p_tcb = p_rdy_list->HeadPtr; /* Decrement time quanta counter */ if (p_tcb == (OS_TCB *)0) { CPU_CRITICAL_EXIT(); return; } #if (OS_CFG_TASK_IDLE_EN > 0u) if (p_tcb == &OSIdleTaskTCB) { CPU_CRITICAL_EXIT(); return; } #endif if (p_tcb->TimeQuantaCtr > 0u) { p_tcb->TimeQuantaCtr--; } if (p_tcb->TimeQuantaCtr > 0u) { /* Task not done with its time quanta */ CPU_CRITICAL_EXIT(); return; } if (p_rdy_list->HeadPtr == p_rdy_list->TailPtr) { /* See if it's time to time slice current task */ CPU_CRITICAL_EXIT(); /* ... only if multiple tasks at same priority */ return; } if (OSSchedLockNestingCtr > 0u) { /* Can't round-robin if the scheduler is locked */ CPU_CRITICAL_EXIT(); return; } OS_RdyListMoveHeadToTail(p_rdy_list); /* Move current OS_TCB to the end of the list */ p_tcb = p_rdy_list->HeadPtr; /* Point to new OS_TCB at head of the list */ if (p_tcb->TimeQuanta == 0u) { /* See if we need to use the default time slice */ p_tcb->TimeQuantaCtr = OSSchedRoundRobinDfltTimeQuanta; } else { p_tcb->TimeQuantaCtr = p_tcb->TimeQuanta; /* Load time slice counter with new time */ } CPU_CRITICAL_EXIT(); } #endif
2.1執行完時間片的程式放在尾部
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void OS_RdyListMoveHeadToTail (OS_RDY_LIST *p_rdy_list) { OS_TCB *p_tcb1; OS_TCB *p_tcb2; OS_TCB *p_tcb3; if (p_rdy_list->HeadPtr != p_rdy_list->TailPtr) { if (p_rdy_list->HeadPtr->NextPtr == p_rdy_list->TailPtr) { /* SWAP the TCBs */ p_tcb1 = p_rdy_list->HeadPtr; /* Point to current head */ p_tcb2 = p_rdy_list->TailPtr; /* Point to current tail */ p_tcb1->PrevPtr = p_tcb2; p_tcb1->NextPtr = (OS_TCB *)0; p_tcb2->PrevPtr = (OS_TCB *)0; p_tcb2->NextPtr = p_tcb1; p_rdy_list->HeadPtr = p_tcb2; p_rdy_list->TailPtr = p_tcb1; } else { p_tcb1 = p_rdy_list->HeadPtr; /* Point to current head */ p_tcb2 = p_rdy_list->TailPtr; /* Point to current tail */ p_tcb3 = p_tcb1->NextPtr; /* Point to new list head */ p_tcb3->PrevPtr = (OS_TCB *)0; /* Adjust back link of new list head */ p_tcb1->NextPtr = (OS_TCB *)0; /* Adjust forward link of new list tail */ p_tcb1->PrevPtr = p_tcb2; /* Adjust back link of new list tail */ p_tcb2->NextPtr = p_tcb1; /* Adjust forward link of old list tail */ p_rdy_list->HeadPtr = p_tcb3; /* Adjust new list head and tail pointers */ p_rdy_list->TailPtr = p_tcb1; } } }
3.更新節拍
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void OS_TickUpdate (OS_TICK ticks) { #if (OS_CFG_TS_EN > 0u) CPU_TS ts_start; #endif CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); OSTickCtr += ticks; /* Keep track of the number of ticks */ OS_TRACE_TICK_INCREMENT(OSTickCtr); #if (OS_CFG_TS_EN > 0u) ts_start = OS_TS_GET(); OS_TickListUpdate(ticks); OSTickTime = OS_TS_GET() - ts_start; if (OSTickTimeMax < OSTickTime) { OSTickTimeMax = OSTickTime; } #else OS_TickListUpdate(ticks); #endif #if (OS_CFG_DYN_TICK_EN > 0u) if (OSTickList.TCB_Ptr != (OS_TCB *)0) { OSTickCtrStep = OSTickList.TCB_Ptr->TickRemain; } else { OSTickCtrStep = 0u; } OS_DynTickSet(OSTickCtrStep); #endif CPU_CRITICAL_EXIT(); }
3.1更新節拍列表
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
static void OS_TickListUpdate (OS_TICK ticks) { OS_TCB *p_tcb; OS_TICK_LIST *p_list; #if (OS_CFG_DBG_EN > 0u) OS_OBJ_QTY nbr_updated; #endif #if (OS_CFG_MUTEX_EN > 0u) OS_TCB *p_tcb_owner; OS_PRIO prio_new; #endif #if (OS_CFG_DBG_EN > 0u) nbr_updated = 0u; #endif p_list = &OSTickList; p_tcb = p_list->TCB_Ptr; if (p_tcb != (OS_TCB *)0) { if (p_tcb->TickRemain <= ticks) { ticks = ticks - p_tcb->TickRemain; p_tcb->TickRemain = 0u; } else { p_tcb->TickRemain -= ticks; } while (p_tcb->TickRemain == 0u) { #if (OS_CFG_DBG_EN > 0u) nbr_updated++; #endif switch (p_tcb->TaskState) { case OS_TASK_STATE_DLY: p_tcb->TaskState = OS_TASK_STATE_RDY; OS_RdyListInsert(p_tcb); /* Insert the task in the ready list */ break; case OS_TASK_STATE_DLY_SUSPENDED: p_tcb->TaskState = OS_TASK_STATE_SUSPENDED; break; default: #if (OS_CFG_MUTEX_EN > 0u) p_tcb_owner = (OS_TCB *)0; if (p_tcb->PendOn == OS_TASK_PEND_ON_MUTEX) { p_tcb_owner = (OS_TCB *)((OS_MUTEX *)((void *)p_tcb->PendObjPtr))->OwnerTCBPtr; } #endif #if (OS_MSG_EN > 0u) p_tcb->MsgPtr = (void *)0; p_tcb->MsgSize = 0u; #endif #if (OS_CFG_TS_EN > 0u) p_tcb->TS = OS_TS_GET(); #endif OS_PendListRemove(p_tcb); /* Remove task from pend list */ switch (p_tcb->TaskState) { case OS_TASK_STATE_PEND_TIMEOUT: OS_RdyListInsert(p_tcb); /* Insert the task in the ready list */ p_tcb->TaskState = OS_TASK_STATE_RDY; break; case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED: p_tcb->TaskState = OS_TASK_STATE_SUSPENDED; break; default: break; } p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */ p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */ #if (OS_CFG_MUTEX_EN > 0u) if (p_tcb_owner != (OS_TCB *)0) { if ((p_tcb_owner->Prio != p_tcb_owner->BasePrio) && (p_tcb_owner->Prio == p_tcb->Prio)) { /* Has the owner inherited a priority? */ prio_new = OS_MutexGrpPrioFindHighest(p_tcb_owner); prio_new = (prio_new > p_tcb_owner->BasePrio) ? p_tcb_owner->BasePrio : prio_new; if (prio_new != p_tcb_owner->Prio) { OS_TaskChangePrio(p_tcb_owner, prio_new); OS_TRACE_MUTEX_TASK_PRIO_DISINHERIT(p_tcb_owner, p_tcb_owner->Prio); } } } #endif break; } p_list->TCB_Ptr = p_tcb->TickNextPtr; p_tcb = p_list->TCB_Ptr; /* Get 'p_tcb' again for loop */ if (p_tcb == (OS_TCB *)0) { #if (OS_CFG_DBG_EN > 0u) p_list->NbrEntries = 0u; #endif break; } else { #if (OS_CFG_DBG_EN > 0u) p_list->NbrEntries--; #endif p_tcb->TickPrevPtr = (OS_TCB *)0; if (p_tcb->TickRemain <= ticks) { ticks = ticks - p_tcb->TickRemain; p_tcb->TickRemain = 0u; } else { p_tcb->TickRemain -= ticks; } } } } #if (OS_CFG_DBG_EN > 0u) p_list->NbrUpdated = nbr_updated; #endif }
3.1.1插入就緒列表
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void OS_RdyListInsert (OS_TCB *p_tcb) { OS_PrioInsert(p_tcb->Prio); if (p_tcb->Prio == OSPrioCur) { /* Are we readying a task at the same prio? */ OS_RdyListInsertTail(p_tcb); /* Yes, insert readied task at the end of the list */ } else { OS_RdyListInsertHead(p_tcb); /* No, insert readied task at the beginning of the list*/ } OS_TRACE_TASK_READY(p_tcb); }
3.1.1.1插入優先順序
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void OS_PrioInsert (OS_PRIO prio) { #if (OS_CFG_PRIO_MAX <= (CPU_CFG_DATA_SIZE * 8u)) /* Optimize for less than word size nbr of priorities */ OSPrioTbl[0] |= (CPU_DATA)1u << (((CPU_CFG_DATA_SIZE * 8u) - 1u) - prio); #elif (OS_CFG_PRIO_MAX <= (2u * (CPU_CFG_DATA_SIZE * 8u))) /* Optimize for 2x the word size nbr of priorities */ if (prio < (CPU_CFG_DATA_SIZE * 8u)) { OSPrioTbl[0] |= (CPU_DATA)1u << (((CPU_CFG_DATA_SIZE * 8u) - 1u) - prio); } else { OSPrioTbl[1] |= (CPU_DATA)1u << (((CPU_CFG_DATA_SIZE * 8u) - 1u) - (prio - (CPU_CFG_DATA_SIZE * 8u))); } #else CPU_DATA bit_nbr; OS_PRIO ix; ix = (OS_PRIO)(prio / (CPU_CFG_DATA_SIZE * 8u)); bit_nbr = (CPU_DATA)prio & ((CPU_CFG_DATA_SIZE * 8u) - 1u); OSPrioTbl[ix] |= (CPU_DATA)1u << (((CPU_CFG_DATA_SIZE * 8u) - 1u) - bit_nbr); #endif }
3.1.1.2插入就緒列表尾部
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void OS_RdyListInsertTail (OS_TCB *p_tcb) { OS_RDY_LIST *p_rdy_list; OS_TCB *p_tcb2; p_rdy_list = &OSRdyList[p_tcb->Prio]; if (p_rdy_list->HeadPtr == (OS_TCB *)0) { /* CASE 0: Insert when there are no entries */ #if (OS_CFG_DBG_EN > 0u) p_rdy_list->NbrEntries = 1u; /* This is the first entry */ #endif p_tcb->NextPtr = (OS_TCB *)0; /* No other OS_TCBs in the list */ p_tcb->PrevPtr = (OS_TCB *)0; p_rdy_list->HeadPtr = p_tcb; /* Both list pointers point to this OS_TCB */ p_rdy_list->TailPtr = p_tcb; } else { /* CASE 1: Insert AFTER the current tail of list */ #if (OS_CFG_DBG_EN > 0u) p_rdy_list->NbrEntries++; /* One more OS_TCB in the list */ #endif p_tcb->NextPtr = (OS_TCB *)0; /* Adjust new OS_TCBs links */ p_tcb2 = p_rdy_list->TailPtr; p_tcb->PrevPtr = p_tcb2; p_tcb2->NextPtr = p_tcb; /* Adjust old tail of list's links */ p_rdy_list->TailPtr = p_tcb; } }
3.1.1.3插入就緒列表頭部
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void OS_RdyListInsertHead (OS_TCB *p_tcb) { OS_RDY_LIST *p_rdy_list; OS_TCB *p_tcb2; p_rdy_list = &OSRdyList[p_tcb->Prio]; if (p_rdy_list->HeadPtr == (OS_TCB *)0) { /* CASE 0: Insert when there are no entries */ #if (OS_CFG_DBG_EN > 0u) p_rdy_list->NbrEntries = 1u; /* This is the first entry */ #endif p_tcb->NextPtr = (OS_TCB *)0; /* No other OS_TCBs in the list */ p_tcb->PrevPtr = (OS_TCB *)0; p_rdy_list->HeadPtr = p_tcb; /* Both list pointers point to this OS_TCB */ p_rdy_list->TailPtr = p_tcb; } else { /* CASE 1: Insert BEFORE the current head of list */ #if (OS_CFG_DBG_EN > 0u) p_rdy_list->NbrEntries++; /* One more OS_TCB in the list */ #endif p_tcb->NextPtr = p_rdy_list->HeadPtr; /* Adjust new OS_TCBs links */ p_tcb->PrevPtr = (OS_TCB *)0; p_tcb2 = p_rdy_list->HeadPtr; /* Adjust old head of list's links */ p_tcb2->PrevPtr = p_tcb; p_rdy_list->HeadPtr = p_tcb; } }
3.1.2從掛起列表移除
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void OS_PendListRemove (OS_TCB *p_tcb) { OS_PEND_LIST *p_pend_list; OS_TCB *p_next; OS_TCB *p_prev; if (p_tcb->PendObjPtr != (OS_PEND_OBJ *)0) { /* Only remove if object has a pend list. */ p_pend_list = &p_tcb->PendObjPtr->PendList; /* Get pointer to pend list */ /* Remove TCB from the pend list. */ if (p_pend_list->HeadPtr->PendNextPtr == (OS_TCB *)0) { p_pend_list->HeadPtr = (OS_TCB *)0; /* Only one entry in the pend list */ p_pend_list->TailPtr = (OS_TCB *)0; } else if (p_tcb->PendPrevPtr == (OS_TCB *)0) { /* See if entry is at the head of the list */ p_next = p_tcb->PendNextPtr; /* Yes */ p_next->PendPrevPtr = (OS_TCB *)0; p_pend_list->HeadPtr = p_next; } else if (p_tcb->PendNextPtr == (OS_TCB *)0) { /* See if entry is at the tail of the list */ p_prev = p_tcb->PendPrevPtr; /* Yes */ p_prev->PendNextPtr = (OS_TCB *)0; p_pend_list->TailPtr = p_prev; } else { p_prev = p_tcb->PendPrevPtr; /* Remove from inside the list */ p_next = p_tcb->PendNextPtr; p_prev->PendNextPtr = p_next; p_next->PendPrevPtr = p_prev; } #if (OS_CFG_DBG_EN > 0u) p_pend_list->NbrEntries--; /* One less entry in the list */ #endif p_tcb->PendNextPtr = (OS_TCB *)0; p_tcb->PendPrevPtr = (OS_TCB *)0; p_tcb->PendObjPtr = (OS_PEND_OBJ *)0; } }
3.1.3獲取互斥量最高優先權
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
OS_PRIO OS_MutexGrpPrioFindHighest (OS_TCB *p_tcb) { OS_MUTEX **pp_mutex; OS_PRIO highest_prio; OS_PRIO prio; OS_TCB *p_head; highest_prio = (OS_PRIO)(OS_CFG_PRIO_MAX - 1u); pp_mutex = &p_tcb->MutexGrpHeadPtr; while(*pp_mutex != (OS_MUTEX *)0) { p_head = (*pp_mutex)->PendList.HeadPtr; if (p_head != (OS_TCB *)0) { prio = p_head->Prio; if(prio < highest_prio) { highest_prio = prio; } } pp_mutex = &(*pp_mutex)->MutexGrpNextPtr; } return (highest_prio); }
3.1.4改變執行任務優先權
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void OS_TaskChangePrio(OS_TCB *p_tcb, OS_PRIO prio_new) { OS_TCB *p_tcb_owner; #if (OS_CFG_MUTEX_EN > 0u) OS_PRIO prio_cur; #endif do { p_tcb_owner = (OS_TCB *)0; #if (OS_CFG_MUTEX_EN > 0u) prio_cur = p_tcb->Prio; #endif switch (p_tcb->TaskState) { case OS_TASK_STATE_RDY: OS_RdyListRemove(p_tcb); /* Remove from current priority */ p_tcb->Prio = prio_new; /* Set new task priority */ OS_PrioInsert(p_tcb->Prio); if (p_tcb == OSTCBCurPtr) { OS_RdyListInsertHead(p_tcb); } else { OS_RdyListInsertTail(p_tcb); } break; case OS_TASK_STATE_DLY: /* Nothing to do except change the priority in the OS_TCB*/ case OS_TASK_STATE_SUSPENDED: case OS_TASK_STATE_DLY_SUSPENDED: p_tcb->Prio = prio_new; /* Set new task priority */ break; case OS_TASK_STATE_PEND: case OS_TASK_STATE_PEND_TIMEOUT: case OS_TASK_STATE_PEND_SUSPENDED: case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED: p_tcb->Prio = prio_new; /* Set new task priority */ switch (p_tcb->PendOn) { /* What to do depends on what we are pending on */ case OS_TASK_PEND_ON_FLAG: case OS_TASK_PEND_ON_Q: case OS_TASK_PEND_ON_SEM: OS_PendListChangePrio(p_tcb); break; case OS_TASK_PEND_ON_MUTEX: #if (OS_CFG_MUTEX_EN > 0u) OS_PendListChangePrio(p_tcb); p_tcb_owner = ((OS_MUTEX *)((void *)p_tcb->PendObjPtr))->OwnerTCBPtr; if (prio_cur > prio_new) { /* Are we increasing the priority? */ if (p_tcb_owner->Prio <= prio_new) { /* Yes, do we need to give this prio to the owner? */ p_tcb_owner = (OS_TCB *)0; } else { /* Block is empty when trace is disabled. */ OS_TRACE_MUTEX_TASK_PRIO_INHERIT(p_tcb_owner, prio_new); } } else { if (p_tcb_owner->Prio == prio_cur) { /* No, is it required to check for a lower prio? */ prio_new = OS_MutexGrpPrioFindHighest(p_tcb_owner); prio_new = (prio_new > p_tcb_owner->BasePrio) ? p_tcb_owner->BasePrio : prio_new; if (prio_new == p_tcb_owner->Prio) { p_tcb_owner = (OS_TCB *)0; } else { /* Block is empty when trace is disabled. */ OS_TRACE_MUTEX_TASK_PRIO_DISINHERIT(p_tcb_owner, prio_new); } } else { p_tcb_owner = (OS_TCB *)0; } } #endif break; case OS_TASK_PEND_ON_TASK_Q: case OS_TASK_PEND_ON_TASK_SEM: default: /* Default case. */ break; } break; default: return; } p_tcb = p_tcb_owner; } while (p_tcb != (OS_TCB *)0); }