📄 os_tmr.c
字号:
OSTmrDbgListPtr->DbgPrevPtr = p_tmr;
}
OSTmrDbgListPtr = p_tmr;
}
void OS_TmrDbgListRemove (OS_TMR *p_tmr)
{
OS_TMR *p_tmr_next;
OS_TMR *p_tmr_prev;
p_tmr_prev = p_tmr->DbgPrevPtr;
p_tmr_next = p_tmr->DbgNextPtr;
if (p_tmr_prev == (OS_TMR *)0) {
OSTmrDbgListPtr = p_tmr_next;
if (p_tmr_next != (OS_TMR *)0) {
p_tmr_next->DbgPrevPtr = (OS_TMR *)0;
}
p_tmr->DbgNextPtr = (OS_TMR *)0;
} else if (p_tmr_next == (OS_TMR *)0) {
p_tmr_prev->DbgNextPtr = (OS_TMR *)0;
p_tmr->DbgPrevPtr = (OS_TMR *)0;
} else {
p_tmr_prev->DbgNextPtr = p_tmr_next;
p_tmr_next->DbgPrevPtr = p_tmr_prev;
p_tmr->DbgNextPtr = (OS_TMR *)0;
p_tmr->DbgPrevPtr = (OS_TMR *)0;
}
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* INITIALIZE THE TIMER MANAGER
*
* Description: This function is called by OSInit() to initialize the timer manager module.
*
* Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
*
* OS_ERR_NONE
* OS_ERR_TMR_STK_INVALID if you didn't specify a stack for the timer task
* OS_ERR_TMR_STK_SIZE_INVALID if you didn't allocate enough space for the timer stack
* OS_ERR_PRIO_INVALID if you specified the same priority as the idle task
* OS_ERR_xxx any error code returned by OSTaskCreate()
*
* Returns : none
*
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
void OS_TmrInit (OS_ERR *p_err)
{
OS_TMR_SPOKE_IX i;
OS_TMR_SPOKE *p_spoke;
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
#if OS_CFG_DBG_EN > 0u
OSTmrDbgListPtr = (OS_TMR *)0;
#endif
if (OSCfg_TmrTaskRate_Hz > (OS_RATE_HZ)0) {
OSTmrUpdateCnt = OSCfg_TickRate_Hz / OSCfg_TmrTaskRate_Hz;
} else {
OSTmrUpdateCnt = OSCfg_TickRate_Hz / (OS_RATE_HZ)10;
}
OSTmrUpdateCtr = OSTmrUpdateCnt;
OSTmrTickCtr = (OS_TICK)0;
OSTmrTaskTimeMax = (CPU_TS)0;
for (i = 0u; i < OSCfg_TmrWheelSize; i++) {
p_spoke = &OSCfg_TmrWheel[i];
p_spoke->NbrEntries = (OS_OBJ_QTY)0;
p_spoke->NbrEntriesMax = (OS_OBJ_QTY)0;
p_spoke->FirstPtr = (OS_TMR *)0;
}
/* ---------------- CREATE THE TIMER TASK --------------- */
if (OSCfg_TmrTaskStkBasePtr == (CPU_STK*)0) {
*p_err = OS_ERR_TMR_STK_INVALID;
return;
}
if (OSCfg_TmrTaskStkSize < OSCfg_StkSizeMin) {
*p_err = OS_ERR_TMR_STK_INVALID;
return;
}
if (OSCfg_TmrTaskPrio >= (OS_CFG_PRIO_MAX - 1u)) {
*p_err = OS_ERR_PRIO_INVALID;
return;
}
OSTaskCreate((OS_TCB *)&OSTmrTaskTCB,
(CPU_CHAR *)((void *)"uC/OS-III Timer Task"),
(OS_TASK_PTR )OS_TmrTask,
(void *)0,
(OS_PRIO )OSCfg_TmrTaskPrio,
(CPU_STK *)OSCfg_TmrTaskStkBasePtr,
(CPU_STK_SIZE)OSCfg_TmrTaskStkLimit,
(CPU_STK_SIZE)OSCfg_TmrTaskStkSize,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void *)0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
(OS_ERR *)p_err);
}
/*$PAGE*/
/*
************************************************************************************************************************
* INSERT A TIMER INTO THE TIMER WHEEL
*
* Description: This function is called to insert the timer into the timer wheel. The timer is always inserted at the
* beginning of the list.
*
* Arguments : p_tmr Is a pointer to the timer to insert.
* -----
*
* opt Is either:
*
* OS_OPT_LINK_PERIODIC Means to re-insert the timer after a period expired
* OS_OPT_LINK_DLY Means to insert the timer the first time
*
* Returns : none
*
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
void OS_TmrLink (OS_TMR *p_tmr,
OS_OPT opt)
{
OS_TMR_SPOKE *p_spoke;
OS_TMR *p_tmr0;
OS_TMR *p_tmr1;
OS_TMR_SPOKE_IX spoke;
p_tmr->State = OS_TMR_STATE_RUNNING;
if (opt == OS_OPT_LINK_PERIODIC) { /* Determine when timer will expire */
p_tmr->Match = p_tmr->Period + OSTmrTickCtr;
} else {
if (p_tmr->Dly == (OS_TICK)0) {
p_tmr->Match = p_tmr->Period + OSTmrTickCtr;
} else {
p_tmr->Match = p_tmr->Dly + OSTmrTickCtr;
}
}
spoke = (OS_TMR_SPOKE_IX)(p_tmr->Match % OSCfg_TmrWheelSize);
p_spoke = &OSCfg_TmrWheel[spoke];
if (p_spoke->FirstPtr == (OS_TMR *)0) { /* Link into timer wheel */
p_tmr->NextPtr = (OS_TMR *)0;
p_tmr->PrevPtr = (OS_TMR *)0;
p_spoke->FirstPtr = p_tmr;
p_spoke->NbrEntries = 1u;
} else {
p_tmr->Remain = p_tmr->Match /* Compute remaining time for timer */
- OSTmrTickCtr;
p_tmr1 = p_spoke->FirstPtr; /* Point to current first timer in the list */
while (p_tmr1 != (OS_TMR *)0) {
p_tmr1->Remain = p_tmr1->Match /* Compute time remaining of current timer in list */
- OSTmrTickCtr;
if (p_tmr->Remain > p_tmr1->Remain) { /* Do we need to insert AFTER current timer in list? */
if (p_tmr1->NextPtr != (OS_TMR *)0) { /* Yes, are we pointing at the last timer in the list? */
p_tmr1 = p_tmr1->NextPtr; /* No, Point to next timer in the list */
} else {
p_tmr->NextPtr = (OS_TMR *)0;
p_tmr->PrevPtr = p_tmr1;
p_tmr1->NextPtr = p_tmr; /* Yes, timer to insert is now new last entry in the list */
p_tmr1 = (OS_TMR *)0; /* Break loop */
}
} else { /* Insert before the current timer */
if (p_tmr1->PrevPtr == (OS_TMR *)0) { /* Are we inserting before the first timer? */
p_tmr->PrevPtr = (OS_TMR *)0;
p_tmr->NextPtr = p_tmr1;
p_tmr1->PrevPtr = p_tmr;
p_spoke->FirstPtr = p_tmr;
} else { /* Insert in between 2 timers already in the list */
p_tmr0 = p_tmr1->PrevPtr;
p_tmr->PrevPtr = p_tmr0;
p_tmr->NextPtr = p_tmr1;
p_tmr0->NextPtr = p_tmr;
p_tmr1->PrevPtr = p_tmr;
}
p_tmr1 = (OS_TMR *)0; /* Break loop */
}
}
p_spoke->NbrEntries++;
}
if (p_spoke->NbrEntriesMax < p_spoke->NbrEntries) { /* Keep track of maximum number of entries in each spoke */
p_spoke->NbrEntriesMax = p_spoke->NbrEntries;
}
}
/*$PAGE*/
/*
************************************************************************************************************************
* RESET TIMER 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_TmrResetPeak (void)
{
OS_TMR_SPOKE *p_spoke;
OS_TMR_SPOKE_IX i;
for (i = 0u; i < OSCfg_TmrWheelSize; i++) {
p_spoke = (OS_TMR_SPOKE *)&OSCfg_TmrWheel[i];
p_spoke->NbrEntriesMax = (OS_OBJ_QTY )0u;
}
}
/*$PAGE*/
/*
************************************************************************************************************************
* REMOVE A TIMER FROM THE TIMER WHEEL
*
* Description: This function is called to remove the timer from the timer wheel.
*
* Arguments : p_tmr Is a pointer to the timer to remove.
* -----
*
* Returns : none
*
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
void OS_TmrUnlink (OS_TMR *p_tmr)
{
OS_TMR_SPOKE *p_spoke;
OS_TMR *p_tmr1;
OS_TMR *p_tmr2;
OS_TMR_SPOKE_IX spoke;
spoke = (OS_TMR_SPOKE_IX)(p_tmr->Match % OSCfg_TmrWheelSize);
p_spoke = &OSCfg_TmrWheel[spoke];
if (p_spoke->FirstPtr == p_tmr) { /* See if timer to remove is at the beginning of list */
p_tmr1 = (OS_TMR *)p_tmr->NextPtr;
p_spoke->FirstPtr = (OS_TMR *)p_tmr1;
if (p_tmr1 != (OS_TMR *)0) {
p_tmr1->PrevPtr = (OS_TMR *)0;
}
} else {
p_tmr1 = (OS_TMR *)p_tmr->PrevPtr; /* Remove timer from somewhere in the list */
p_tmr2 = (OS_TMR *)p_tmr->NextPtr;
p_tmr1->NextPtr = p_tmr2;
if (p_tmr2 != (OS_TMR *)0) {
p_tmr2->PrevPtr = (OS_TMR *)p_tmr1;
}
}
p_tmr->State = OS_TMR_STATE_STOPPED;
p_tmr->NextPtr = (OS_TMR *)0;
p_tmr->PrevPtr = (OS_TMR *)0;
p_spoke->NbrEntries--;
}
/*$PAGE*/
/*
************************************************************************************************************************
* TIMER MANAGEMENT TASK
*
* Description: This task is created by OS_TmrInit().
*
* Arguments : none
*
* Returns : none
*
* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
************************************************************************************************************************
*/
void OS_TmrTask (void *p_arg)
{
CPU_BOOLEAN done;
OS_ERR err;
OS_TMR_CALLBACK_PTR p_fnct;
OS_TMR_SPOKE *p_spoke;
OS_TMR *p_tmr;
OS_TMR *p_tmr_next;
OS_TMR_SPOKE_IX spoke;
CPU_TS ts;
CPU_TS ts_start;
CPU_TS ts_end;
p_arg = p_arg; /* Not using 'p_arg', prevent compiler warning */
while (DEF_ON) {
(void)OSTaskSemPend((OS_TICK )0, /* Wait for signal indicating time to update tmrs */
(OS_OPT )OS_OPT_PEND_BLOCKING,
(CPU_TS *)&ts,
(OS_ERR *)&err);
OSSchedLock(&err);
ts_start = OS_TS_GET();
OSTmrTickCtr++; /* Increment the current time */
spoke = (OS_TMR_SPOKE_IX)(OSTmrTickCtr % OSCfg_TmrWheelSize);
p_spoke = &OSCfg_TmrWheel[spoke];
p_tmr = p_spoke->FirstPtr;
done = DEF_FALSE;
while (done == DEF_FALSE) {
if (p_tmr != (OS_TMR *)0) {
p_tmr_next = (OS_TMR *)p_tmr->NextPtr; /* Point to next tmr to update because current ... */
/* ... timer could get unlinked from the wheel. */
if (OSTmrTickCtr == p_tmr->Match) { /* Process each timer that expires */
OS_TmrUnlink(p_tmr); /* Remove from current wheel spoke */
if (p_tmr->Opt == OS_OPT_TMR_PERIODIC) {
OS_TmrLink(p_tmr,
OS_OPT_LINK_PERIODIC); /* Recalculate new position of timer in wheel */
} else {
p_tmr->State = OS_TMR_STATE_COMPLETED; /* Indicate that the timer has completed */
}
p_fnct = p_tmr->CallbackPtr; /* Execute callback function if available */
if (p_fnct != (OS_TMR_CALLBACK_PTR)0) {
(*p_fnct)((void *)p_tmr,
p_tmr->CallbackPtrArg);
}
p_tmr = p_tmr_next; /* See if next timer matches */
} else {
done = DEF_TRUE;
}
} else {
done = DEF_TRUE;
}
}
ts_end = OS_TS_GET() - ts_start; /* Measure execution time of timer task */
OSSchedUnlock(&err);
if (ts_end > OSTmrTaskTimeMax) {
OSTmrTaskTimeMax = ts_end;
}
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -