📄 os_tick.c
字号:
p_tcb->TickSpokePtr = (OS_TICK_SPOKE *)0;
*p_err = OS_ERR_TIME_ZERO_DLY; /* ... do NOT delay. */
return;
}
spoke = (OS_TICK_SPOKE_IX)(p_tcb->TickCtrMatch % OSCfg_TickWheelSize);
p_spoke = &OSCfg_TickWheel[spoke];
if (p_spoke->NbrEntries == (OS_OBJ_QTY)0u) { /* First entry in the spoke */
p_tcb->TickNextPtr = (OS_TCB *)0;
p_tcb->TickPrevPtr = (OS_TCB *)0;
p_spoke->FirstPtr = p_tcb;
p_spoke->NbrEntries = (OS_OBJ_QTY)1u;
} else {
p_tcb1 = p_spoke->FirstPtr; /* Point to current first TCB in the list */
while (p_tcb1 != (OS_TCB *)0) {
p_tcb1->TickRemain = p_tcb1->TickCtrMatch /* Compute time remaining of current TCB in list */
- OSTickCtr;
if (p_tcb->TickRemain > p_tcb1->TickRemain) { /* Do we need to insert AFTER current TCB in list? */
if (p_tcb1->TickNextPtr != (OS_TCB *)0) { /* Yes, are we pointing at the last TCB in the list? */
p_tcb1 = p_tcb1->TickNextPtr; /* No, Point to next TCB in the list */
} else {
p_tcb->TickNextPtr = (OS_TCB *)0;
p_tcb->TickPrevPtr = p_tcb1;
p_tcb1->TickNextPtr = p_tcb; /* Yes, TCB to add is now new last entry in the list */
p_tcb1 = (OS_TCB *)0; /* Break loop */
}
} else { /* Insert before the current TCB */
if (p_tcb1->TickPrevPtr == (OS_TCB *)0) { /* Are we inserting before the first TCB? */
p_tcb->TickPrevPtr = (OS_TCB *)0;
p_tcb->TickNextPtr = p_tcb1;
p_tcb1->TickPrevPtr = p_tcb;
p_spoke->FirstPtr = p_tcb;
} else { /* Insert in between 2 TCBs already in the list */
p_tcb0 = p_tcb1->TickPrevPtr;
p_tcb->TickPrevPtr = p_tcb0;
p_tcb->TickNextPtr = p_tcb1;
p_tcb0->TickNextPtr = p_tcb;
p_tcb1->TickPrevPtr = p_tcb;
}
p_tcb1 = (OS_TCB *)0; /* Break loop */
}
}
p_spoke->NbrEntries++;
}
if (p_spoke->NbrEntriesMax < p_spoke->NbrEntries) { /* Keep track of maximum # of entries in each spoke */
p_spoke->NbrEntriesMax = p_spoke->NbrEntries;
}
p_tcb->TickSpokePtr = p_spoke; /* Link back to tick spoke */
*p_err = OS_ERR_NONE;
}
/*$PAGE*/
/*
************************************************************************************************************************
* REMOVE A TASK FROM THE TICK LIST
*
* Description: This function is called to remove a task from the tick list
*
* Arguments : p_tcb Is a pointer to the OS_TCB to remove.
* -----
*
* Returns : none
*
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
*
* 2) This function is assumed to be called with interrupts disabled.
************************************************************************************************************************
*/
void OS_TickListRemove (OS_TCB *p_tcb)
{
OS_TICK_SPOKE *p_spoke;
OS_TCB *p_tcb1;
OS_TCB *p_tcb2;
p_spoke = p_tcb->TickSpokePtr;
if (p_spoke != (OS_TICK_SPOKE *)0) { /* Confirm that task is in tick list */
p_tcb->TickRemain = (OS_TICK)0u;
if (p_spoke->FirstPtr == p_tcb) { /* Is timer to remove at the beginning of list? */
p_tcb1 = (OS_TCB *)p_tcb->TickNextPtr; /* Yes */
p_spoke->FirstPtr = p_tcb1;
if (p_tcb1 != (OS_TCB *)0) {
p_tcb1->TickPrevPtr = (void *)0;
}
} else {
p_tcb1 = p_tcb->TickPrevPtr; /* No, remove timer from somewhere in the list */
p_tcb2 = p_tcb->TickNextPtr;
p_tcb1->TickNextPtr = p_tcb2;
if (p_tcb2 != (OS_TCB *)0) {
p_tcb2->TickPrevPtr = p_tcb1;
}
}
p_tcb->TickNextPtr = (OS_TCB *)0;
p_tcb->TickPrevPtr = (OS_TCB *)0;
p_tcb->TickSpokePtr = (OS_TICK_SPOKE *)0;
p_tcb->TickCtrMatch = (OS_TICK )0u;
p_spoke->NbrEntries--;
}
}
/*$PAGE*/
/*
************************************************************************************************************************
* RESET TICK LIST PEAK DETECTOR
*
* Description: This function is used to reset the peak detector for the number of entries in each spoke.
*
* Arguments : void
*
* Returns : none
*
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
************************************************************************************************************************
*/
void OS_TickListResetPeak (void)
{
OS_TICK_SPOKE_IX i;
OS_TICK_SPOKE *p_spoke;
for (i = 0u; i < OSCfg_TickWheelSize; i++) {
p_spoke = (OS_TICK_SPOKE *)&OSCfg_TickWheel[i];
p_spoke->NbrEntriesMax = (OS_OBJ_QTY )0u;
}
}
/*$PAGE*/
/*
************************************************************************************************************************
* UPDATE THE TICK LIST
*
* Description: This function is called when a tick occurs and determines if the timeout waiting for a kernel object has
* expired or a delay has expired.
*
* Arguments : non
*
* Returns : none
*
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
void OS_TickListUpdate (void)
{
CPU_BOOLEAN done;
OS_TICK_SPOKE *p_spoke;
OS_TCB *p_tcb;
OS_TCB *p_tcb_next;
OS_TICK_SPOKE_IX spoke;
CPU_TS ts_start;
CPU_TS ts_end;
CPU_SR_ALLOC();
OS_CRITICAL_ENTER();
ts_start = OS_TS_GET();
OSTickCtr++; /* Keep track of the number of ticks */
spoke = (OS_TICK_SPOKE_IX)(OSTickCtr % OSCfg_TickWheelSize);
p_spoke = &OSCfg_TickWheel[spoke];
p_tcb = p_spoke->FirstPtr;
done = DEF_FALSE;
while (done == DEF_FALSE) {
if (p_tcb != (OS_TCB *)0) {
p_tcb_next = p_tcb->TickNextPtr; /* Point to next TCB to update */
switch (p_tcb->TaskState) {
case OS_TASK_STATE_RDY:
case OS_TASK_STATE_PEND:
case OS_TASK_STATE_SUSPENDED:
case OS_TASK_STATE_PEND_SUSPENDED:
break;
case OS_TASK_STATE_DLY:
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
- OSTickCtr;
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
p_tcb->TaskState = OS_TASK_STATE_RDY;
OS_TaskRdy(p_tcb); /* Make task ready to run */
} else {
done = DEF_TRUE; /* Don't find a match, we're done! */
}
break;
case OS_TASK_STATE_PEND_TIMEOUT:
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
- OSTickCtr;
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
#if (OS_MSG_EN > 0u)
p_tcb->MsgPtr = (void *)0;
p_tcb->MsgSize = (OS_MSG_SIZE)0u;
#endif
p_tcb->TS = OS_TS_GET();
OS_PendListRemove(p_tcb); /* Remove from wait list */
OS_TaskRdy(p_tcb);
p_tcb->TaskState = OS_TASK_STATE_RDY;
p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */
p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */
} else {
done = DEF_TRUE; /* Don't find a match, we're done! */
}
break;
case OS_TASK_STATE_DLY_SUSPENDED:
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
- OSTickCtr;
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
OS_TickListRemove(p_tcb); /* Remove from current wheel spoke */
} else {
done = DEF_TRUE; /* Don't find a match, we're done! */
}
break;
case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
- OSTickCtr;
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
#if (OS_MSG_EN > 0u)
p_tcb->MsgPtr = (void *)0;
p_tcb->MsgSize = (OS_MSG_SIZE)0u;
#endif
p_tcb->TS = OS_TS_GET();
OS_PendListRemove(p_tcb); /* Remove from wait list */
OS_TickListRemove(p_tcb); /* Remove from current wheel spoke */
p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */
p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */
} else {
done = DEF_TRUE; /* Don't find a match, we're done! */
}
break;
default:
break;
}
p_tcb = p_tcb_next;
} else {
done = DEF_TRUE;
}
}
ts_end = OS_TS_GET() - ts_start; /* Measure execution time of tick task */
if (ts_end > OSTickTaskTimeMax) {
OSTickTaskTimeMax = ts_end;
}
OS_CRITICAL_EXIT();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -