📄 os_tmr.c
字号:
#endif
/*
************************************************************************************************************************
* RETURN A TIMER TO THE FREE LIST
*
* Description: This function is called to return a timer object to the free list of timers.
*
* Arguments : ptmr is a pointer to the timer to free
*
* Returns : none
************************************************************************************************************************
*/
#if OS_TMR_EN > 0
static void OSTmr_Free (OS_TMR *ptmr)
{
ptmr->OSTmrState = OS_TMR_STATE_UNUSED; /* Clear timer object fields */
ptmr->OSTmrOpt = OS_TMR_OPT_NONE;
ptmr->OSTmrPeriod = 0;
ptmr->OSTmrMatch = 0;
ptmr->OSTmrCallback = (OS_TMR_CALLBACK)0;
ptmr->OSTmrCallbackArg = (void *)0;
#if OS_TMR_CFG_NAME_SIZE > 1
ptmr->OSTmrName[0] = '?'; /* Unknown name */
ptmr->OSTmrName[1] = OS_ASCII_NUL;
#endif
ptmr->OSTmrPrev = (OS_TCB *)0; /* Chain timer to free list */
ptmr->OSTmrNext = OSTmrFreeList;
OSTmrFreeList = ptmr;
OSTmrUsed--; /* Update timer object statistics */
OSTmrFree++;
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* INITIALIZATION
* INITIALIZE THE FREE LIST OF TIMERS
*
* Description: This function is called by OSInit() to initialize the free list of OS_TMRs.
*
* Arguments : none
*
* Returns : none
************************************************************************************************************************
*/
#if OS_TMR_EN > 0
void OSTmr_Init (void)
{
#if OS_EVENT_NAME_SIZE > 10
INT8U err;
#endif
INT16U i;
OS_TMR *ptmr1;
OS_TMR *ptmr2;
OS_MemClr((INT8U *)&OSTmrTbl[0], sizeof(OSTmrTbl)); /* Clear all the TMRs */
OS_MemClr((INT8U *)&OSTmrWheelTbl[0], sizeof(OSTmrWheelTbl)); /* Clear the timer wheel */
ptmr1 = &OSTmrTbl[0];
ptmr2 = &OSTmrTbl[1];
for (i = 0; i < (OS_TMR_CFG_MAX - 1); i++) { /* Init. list of free TMRs */
ptmr1->OSTmrType = OS_TMR_TYPE;
ptmr1->OSTmrState = OS_TMR_STATE_UNUSED; /* Indicate that timer is inactive */
ptmr1->OSTmrNext = (void *)ptmr2; /* Link to next timer */
#if OS_TMR_CFG_NAME_SIZE > 1
ptmr1->OSTmrName[0] = '?'; /* Unknown name */
ptmr1->OSTmrName[1] = OS_ASCII_NUL;
#endif
ptmr1++;
ptmr2++;
}
ptmr1->OSTmrType = OS_TMR_TYPE;
ptmr1->OSTmrState = OS_TMR_STATE_UNUSED; /* Indicate that timer is inactive */
ptmr1->OSTmrNext = (void *)0; /* Last OS_TMR */
#if OS_TMR_CFG_NAME_SIZE > 1
ptmr1->OSTmrName[0] = '?'; /* Unknown name */
ptmr1->OSTmrName[1] = OS_ASCII_NUL;
#endif
OSTmrTime = 0;
OSTmrUsed = 0;
OSTmrFree = OS_TMR_CFG_MAX;
OSTmrFreeList = &OSTmrTbl[0];
OSTmrSem = OSSemCreate(1);
OSTmrSemSignal = OSSemCreate(0);
#if OS_EVENT_NAME_SIZE > 18
OSEventNameSet(OSTmrSem, (INT8U *)"uC/OS-II TmrLock", &err);/* Assign names to semaphores */
#else
#if OS_EVENT_NAME_SIZE > 10
OSEventNameSet(OSTmrSem, (INT8U *)"OS-TmrLock", &err);
#endif
#endif
#if OS_EVENT_NAME_SIZE > 18
OSEventNameSet(OSTmrSemSignal, (INT8U *)"uC/OS-II TmrSignal", &err);
#else
#if OS_EVENT_NAME_SIZE > 10
OSEventNameSet(OSTmrSemSignal, (INT8U *)"OS-TmrSig", &err);
#endif
#endif
OSTmr_InitTask();
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* INITIALIZE THE TIMER MANAGEMENT TASK
*
* Description: This function is called by OSTmrInit() to create the timer management task.
*
* Arguments : none
*
* Returns : none
************************************************************************************************************************
*/
#if OS_TMR_EN > 0
static void OSTmr_InitTask (void)
{
#if OS_TASK_NAME_SIZE > 6
INT8U err;
#endif
#if OS_TASK_CREATE_EXT_EN > 0
#if OS_STK_GROWTH == 1
(void)OSTaskCreateExt(OSTmr_Task,
(void *)0, /* No arguments passed to OSTmrTask() */
&OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1], /* Set Top-Of-Stack */
OS_TASK_TMR_PRIO,
OS_TASK_TMR_ID,
&OSTmrTaskStk[0], /* Set Bottom-Of-Stack */
OS_TASK_TMR_STK_SIZE,
(void *)0, /* No TCB extension */
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear stack */
#else
(void)OSTaskCreateExt(OSTmr_Task,
(void *)0, /* No arguments passed to OSTmrTask() */
&OSTmrTaskStk[0], /* Set Top-Of-Stack */
OS_TASK_TMR_PRIO,
OS_TASK_TMR_ID,
&OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1], /* Set Bottom-Of-Stack */
OS_TASK_TMR_STK_SIZE,
(void *)0, /* No TCB extension */
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear stack */
#endif
#else
#if OS_STK_GROWTH == 1
(void)OSTaskCreate(OSTmr_Task,
(void *)0,
&OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1],
OS_TASK_TMR_PRIO);
#else
(void)OSTaskCreate(OSTmr_Task,
(void *)0,
&OSTmrTaskStk[0],
OS_TASK_TMR_PRIO);
#endif
#endif
#if OS_TASK_NAME_SIZE > 12
OSTaskNameSet(OS_TASK_TMR_PRIO, (INT8U *)"uC/OS-II Tmr", &err);
#else
#if OS_TASK_NAME_SIZE > 6
OSTaskNameSet(OS_TASK_TMR_PRIO, (INT8U *)"OS-Tmr", &err);
#endif
#endif
}
#endif
/*$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 : ptmr Is a pointer to the timer to insert.
*
* type Is either:
* OS_TMR_LINK_PERIODIC Means to re-insert the timer after a period expired
* OS_TMR_LINK_DLY Means to insert the timer the first time
*
* Returns : none
************************************************************************************************************************
*/
#if OS_TMR_EN > 0
static void OSTmr_Link (OS_TMR *ptmr, INT8U type)
{
OS_TMR *ptmr1;
OS_TMR_WHEEL *pspoke;
INT16U spoke;
ptmr->OSTmrState = OS_TMR_STATE_RUNNING;
if (type == OS_TMR_LINK_PERIODIC) { /* Determine when timer will expire */
ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;
} else {
if (ptmr->OSTmrDly == 0) {
ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;
} else {
ptmr->OSTmrMatch = ptmr->OSTmrDly + OSTmrTime;
}
}
spoke = ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE;
pspoke = &OSTmrWheelTbl[spoke];
if (pspoke->OSTmrFirst == (OS_TMR *)0) { /* Link into timer wheel */
pspoke->OSTmrFirst = ptmr;
ptmr->OSTmrNext = (OS_TMR *)0;
pspoke->OSTmrEntries = 1;
} else {
ptmr1 = pspoke->OSTmrFirst; /* Point to first timer in the spoke */
pspoke->OSTmrFirst = ptmr;
ptmr->OSTmrNext = (void *)ptmr1;
ptmr1->OSTmrPrev = (void *)ptmr;
pspoke->OSTmrEntries++;
}
ptmr->OSTmrPrev = (void *)0; /* Timer always inserted as first node in list */
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* REMOVE A TIMER FROM THE TIMER WHEEL
*
* Description: This function is called to remove the timer from the timer wheel.
*
* Arguments : ptmr Is a pointer to the timer to remove.
*
* Returns : none
************************************************************************************************************************
*/
#if OS_TMR_EN > 0
static void OSTmr_Unlink (OS_TMR *ptmr)
{
OS_TMR *ptmr1;
OS_TMR *ptmr2;
OS_TMR_WHEEL *pspoke;
INT16U spoke;
spoke = ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE;
pspoke = &OSTmrWheelTbl[spoke];
if (pspoke->OSTmrFirst == ptmr) { /* See if timer to remove is at the beginning of list */
ptmr1 = (OS_TMR *)ptmr->OSTmrNext;
pspoke->OSTmrFirst = ptmr1;
if (ptmr1 != (OS_TMR *)0) {
ptmr1->OSTmrPrev = (void *)0;
}
} else {
ptmr1 = ptmr->OSTmrPrev; /* Remove timer from somewhere in the list */
ptmr2 = ptmr->OSTmrNext;
ptmr1->OSTmrNext = ptmr2;
if (ptmr2 != (OS_TMR *)0) {
ptmr2->OSTmrPrev = ptmr1;
}
}
ptmr->OSTmrState = OS_TMR_STATE_STOPPED;
ptmr->OSTmrNext = (void *)0;
ptmr->OSTmrPrev = (void *)0;
pspoke->OSTmrEntries--;
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* TIMER MANAGER DATA STRUCTURE LOCKING MECHANISM
*
* Description: These functions are used to gain exclusive access to timer management data structures.
*
* Arguments : none
*
* Returns : none
************************************************************************************************************************
*/
#if OS_TMR_EN > 0
static void OSTmr_Lock (void)
{
INT8U err;
OSSemPend(OSTmrSem, 0, &err);
(void)err;
}
#endif
#if OS_TMR_EN > 0
static void OSTmr_Unlock (void)
{
(void)OSSemPost(OSTmrSem);
}
#endif
/*$PAGE*/
/*
************************************************************************************************************************
* TIMER MANAGEMENT TASK
*
* Description: This task is created by OSTmrInit().
*
* Arguments : none
*
* Returns : none
************************************************************************************************************************
*/
#if OS_TMR_EN > 0
static void OSTmr_Task (void *p_arg)
{
INT8U err;
OS_TMR *ptmr;
OS_TMR *ptmr_next;
OS_TMR_CALLBACK pfnct;
OS_TMR_WHEEL *pspoke;
INT16U spoke;
(void)p_arg; /* Not using 'p_arg', prevent compiler warning */
for (;;) {
OSSemPend(OSTmrSemSignal, 0, &err); /* Wait for signal indicating time to update timers */
OSTmr_Lock();
OSTmrTime++; /* Increment the current time */
spoke = OSTmrTime % OS_TMR_CFG_WHEEL_SIZE; /* Position on current timer wheel entry */
pspoke = &OSTmrWheelTbl[spoke];
ptmr = pspoke->OSTmrFirst;
while (ptmr != (OS_TMR *)0) {
ptmr_next = ptmr->OSTmrNext; /* Point to next timer to update because current ... */
/* ... timer could get unlinked from the wheel. */
if (OSTmrTime == ptmr->OSTmrMatch) { /* Process each timer that expires */
pfnct = ptmr->OSTmrCallback; /* Execute callback function if available */
if (pfnct != (OS_TMR_CALLBACK)0) {
(*pfnct)(ptmr, ptmr->OSTmrCallbackArg);
}
OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */
if (ptmr->OSTmrOpt == OS_TMR_OPT_PERIODIC) {
OSTmr_Link(ptmr, OS_TMR_LINK_PERIODIC); /* Recalculate new position of timer in wheel */
} else {
ptmr->OSTmrState = OS_TMR_STATE_COMPLETED; /* Indicate that the timer has completed */
}
}
ptmr = ptmr_next;
}
OSTmr_Unlock();
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -