astroboy astroboy
/
CoOS_LWIP
Quick and dirty CoOS + LWIP ( Webserver )
Diff: CoOS/kernel/timer.c
- Revision:
- 0:94897d537b31
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CoOS/kernel/timer.c Sat Sep 10 22:41:10 2011 +0000 @@ -0,0 +1,447 @@ +/** + ******************************************************************************* + * @file timer.c + * @version V1.1.4 + * @date 2011.04.20 + * @brief timer management implementation code of CooCox CoOS kernel. + ******************************************************************************* + * @copy + * + * INTERNAL FILE,DON'T PUBLIC. + * + * <h2><center>© COPYRIGHT 2009 CooCox </center></h2> + ******************************************************************************* + */ + + + +/*---------------------------- Include ---------------------------------------*/ +#include <coocox.h> + +/*---------------------------- Variable Define -------------------------------*/ +#if CFG_TMR_EN > 0 + +TmrCtrl TmrTbl[CFG_MAX_TMR]= {{0}};/*!< Table which save timer control block.*/ +P_TmrCtrl TmrList = Co_NULL; /*!< The header of the TmrCtrl list. */ +U32 TmrIDVessel = 0; /*!< Timer ID container. */ + + +/** + ******************************************************************************* + * @brief Insert a timer into the timer list + * @param[in] tmrID Specify timer ID which insertted. + * @param[out] None + * @retval E_INVALID_ID Timer ID passed was invalid,insert fail. + * @retval E_OK Insert successful. + * + * @par Description + * @details This function is called to insert a timer into the timer list. + ******************************************************************************* + */ +static void InsertTmrList(OS_TCID tmrID) +{ + P_TmrCtrl pTmr; + S32 deltaTicks; + U32 tmrCnt; + tmrCnt = TmrTbl[tmrID].tmrCnt; /* Get timer time */ + + if(tmrCnt == 0) /* Is timer time==0? */ + { + return; /* Do nothing,return */ + } + + OsSchedLock(); /* Lock schedule */ + if(TmrList == Co_NULL) /* Is no item in timer list? */ + { + TmrList = &TmrTbl[tmrID]; /* Yes,set this as first item */ + } + else /* No,find correct place ,and insert inserted timer */ + { + pTmr = TmrList; + deltaTicks = tmrCnt; /* Get timer tick */ + + /* find correct place */ + while(pTmr != Co_NULL) + { + deltaTicks -= pTmr->tmrCnt; /* Get ticks with previous item */ + if(deltaTicks < 0) /* Is delta ticks<0? */ + { + /* Yes,get correct place */ + if(pTmr->tmrPrev!= Co_NULL)/* Is head item of timer list? */ + { + /* No,insert into */ + pTmr->tmrPrev->tmrNext = &TmrTbl[tmrID]; + TmrTbl[tmrID].tmrPrev = pTmr->tmrPrev; + TmrTbl[tmrID].tmrNext = pTmr; + pTmr->tmrPrev = &TmrTbl[tmrID]; + } + else /* Yes,set task as first item */ + { + TmrTbl[tmrID].tmrNext = TmrList; + TmrList->tmrPrev = &TmrTbl[tmrID]; + TmrList = &TmrTbl[tmrID]; + } + TmrTbl[tmrID].tmrCnt = TmrTbl[tmrID].tmrNext->tmrCnt+deltaTicks; + TmrTbl[tmrID].tmrNext->tmrCnt -= TmrTbl[tmrID].tmrCnt; + break; + } + /* Is last item in list? */ + else if((deltaTicks >= 0) && (pTmr->tmrNext == Co_NULL)) + { + /* Yes,insert into */ + TmrTbl[tmrID].tmrPrev = pTmr; + pTmr->tmrNext = &TmrTbl[tmrID]; + TmrTbl[tmrID].tmrCnt = deltaTicks; + break; + } + pTmr = pTmr->tmrNext; /* Get the next item in timer list */ + } + } + OsSchedUnlock(); /* Unlock schedule */ +} + + +/** + ******************************************************************************* + * @brief Remove a timer from the timer list + * @param[in] tmrID Specify ID for a timer which removed form timer list. + * @param[out] None + * @retval None + * + * @par Description + * @details This function is called to remove a timer from the timer list. + ******************************************************************************* + */ +static void RemoveTmrList(OS_TCID tmrID) +{ + P_TmrCtrl pTmr; + + pTmr = &TmrTbl[tmrID]; + + OsSchedLock(); /* Lock schedule */ + + /* Is there only one item in timer list? */ + if((pTmr->tmrPrev == Co_NULL) && (pTmr->tmrNext == Co_NULL)) + { + TmrList = Co_NULL; /* Yes,set timer list as Co_NULL */ + } + else if(pTmr->tmrPrev == Co_NULL) /* Is the first item in timer list? */ + { /* Yes,remove timer from list,and reset timer list */ + TmrList = pTmr->tmrNext; + TmrList->tmrPrev = Co_NULL; + pTmr->tmrNext->tmrCnt += pTmr->tmrCnt; + pTmr->tmrNext = Co_NULL; + } + else if(pTmr->tmrNext == Co_NULL) /* Is the last item in timer list? */ + { + /* Yes,remove timer form list */ + pTmr->tmrPrev->tmrNext = Co_NULL; + pTmr->tmrPrev = Co_NULL; + } + else /* No, remove timer from list */ + { + pTmr->tmrPrev->tmrNext = pTmr->tmrNext; + pTmr->tmrNext->tmrPrev = pTmr->tmrPrev; + pTmr->tmrNext->tmrCnt += pTmr->tmrCnt; + pTmr->tmrNext = Co_NULL; + pTmr->tmrPrev = Co_NULL; + } + OsSchedUnlock(); /* Unlock schedule */ +} + + +/** + ******************************************************************************* + * @brief Create a timer + * @param[in] tmrType Specify timer's type. + * @param[in] tmrCnt Specify timer initial counter value. + * @param[in] tmrReload Specify timer reload value. + * @param[in] func Specify timer callback function entry. + * @param[out] None + * @retval E_CREATE_FAIL Create timer fail. + * @retval others Create timer successful. + * + * @par Description + * @details This function is called to create a timer. + ******************************************************************************* + */ +OS_TCID CoCreateTmr(U8 tmrType, U32 tmrCnt, U32 tmrReload, vFUNCPtr func) +{ + U8 i; +#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ + if((tmrType != TMR_TYPE_ONE_SHOT) && (tmrType != TMR_TYPE_PERIODIC)) + { + return E_CREATE_FAIL; + } + if(func == Co_NULL) + { + return E_CREATE_FAIL; + } +#endif + OsSchedLock(); /* Lock schedule */ + for(i = 0; i < CFG_MAX_TMR; i++) + { + if((TmrIDVessel & (1 << i)) == 0) /* Is free timer ID? */ + { + TmrIDVessel |= (1<<i); /* Yes,assign ID to this timer */ + OsSchedUnlock(); /* Unlock schedule */ + TmrTbl[i].tmrID = i; /* Initialize timer as user set */ + TmrTbl[i].tmrType = tmrType; + TmrTbl[i].tmrState = TMR_STATE_STOPPED; + TmrTbl[i].tmrCnt = tmrCnt; + TmrTbl[i].tmrReload = tmrReload; + TmrTbl[i].tmrCallBack = func; + TmrTbl[i].tmrPrev = Co_NULL; + TmrTbl[i].tmrNext = Co_NULL; + return i; /* Return timer ID */ + } + } + OsSchedUnlock(); /* Unlock schedule */ + return E_CREATE_FAIL; /* Error return */ +} + + +/** + ******************************************************************************* + * @brief Start counter + * @param[in] tmrID Specify a timer which startted. + * @param[out] None + * @retval E_INVALID_ID The timer id passed was invalid,can't start timer + * @retval E_OK Insert a timer to timer list and start it successful. + * + * @par Description + * @details This function is called to make a timer start countering. + ******************************************************************************* + */ +StatusType CoStartTmr(OS_TCID tmrID) +{ +#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ + if(tmrID >= CFG_MAX_TMR) + { + return E_INVALID_ID; + } + if( (TmrIDVessel & (1<<tmrID)) == 0) + { + return E_INVALID_ID; + } +#endif + + if(TmrTbl[tmrID].tmrState == TMR_STATE_RUNNING) /* Is timer running? */ + { + return E_OK; /* Yes,do nothing,return OK */ + } + + /* No,set timer status as TMR_STATE_RUNNING */ + TmrTbl[tmrID].tmrState = TMR_STATE_RUNNING; + InsertTmrList(tmrID); /* Insert this timer into timer list */ + return E_OK; /* Return OK */ +} + + + +/** + ******************************************************************************* + * @brief Stop countering for a spcify timer + * @param[in] tmrID Specify a timer which stopped. + * @param[out] None + * @retval E_INVALID_ID The timer id passed was invalid, stop failure. + * @retval E_OK Stop a timer countering successful. + * + * @par Description + * @details This function is called to stop a timer from counting. + ******************************************************************************* + */ +StatusType CoStopTmr(OS_TCID tmrID) +{ +#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ + if(tmrID >= CFG_MAX_TMR) + { + return E_INVALID_ID; + } + if((TmrIDVessel & (1<<tmrID)) == 0) + { + return E_INVALID_ID; + } +#endif + + + if(TmrTbl[tmrID].tmrState == TMR_STATE_STOPPED)/* Does timer stop running?*/ + { + return E_OK; /* Yes,do nothing,return OK */ + } + RemoveTmrList(tmrID); /* No,remove this timer from timer list */ + + /* Set timer status as TMR_STATE_STOPPED */ + TmrTbl[tmrID].tmrState = TMR_STATE_STOPPED; + return E_OK; /* Return OK */ +} + + +/** + ******************************************************************************* + * @brief Delete a timer + * @param[in] tmrID Specify a timer which deleted. + * @param[out] None + * @retval E_INVALID_ID The timer id passed was invalid,deleted failure. + * @retval E_OK Delete a timer successful. + * + * @par Description + * @details This function is called to delete a timer which created before. + ******************************************************************************* + */ +StatusType CoDelTmr(OS_TCID tmrID) +{ +#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ + if(tmrID >= CFG_MAX_TMR) + { + return E_INVALID_ID; + } + if( (TmrIDVessel & (1<<tmrID)) == 0) + { + return E_INVALID_ID; + } +#endif + + if(TmrTbl[tmrID].tmrState == TMR_STATE_RUNNING) /* Is timer running? */ + { + RemoveTmrList(tmrID); /* Yes,remove this timer from timer list*/ + } + TmrIDVessel &=~(1<<tmrID); /* Release resource that this timer hold*/ + return E_OK; /* Return OK */ +} + + +/** + ******************************************************************************* + * @brief Get current counter of specify timer + * @param[in] tmrID Specify timer by ID. + * @param[out] E_INVALID_ID Invalid ID was passed and get counter failure. + * @param[out] E_OK Get current counter successful. + * @retval Current counter of a timer which specify by id. + * + * @par Description + * @details This function is called to obtain current counter of specify timer. + ******************************************************************************* + */ +U32 CoGetCurTmrCnt(OS_TCID tmrID,StatusType* perr) +{ +#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ + if(tmrID >= CFG_MAX_TMR) + { + *perr = E_INVALID_ID; + return 0; + } + if((TmrIDVessel & (1<<tmrID)) == 0) + { + *perr = E_INVALID_ID; + return 0; + } +#endif + *perr = E_OK; + return TmrTbl[tmrID].tmrCnt; /* Return timer counter */ +} + + +/** + ******************************************************************************* + * @brief Setting for a specify timer + * @param[in] tmrID Specify timer by ID. + * @param[in] tmrCnt Specify timer counter which need to be set. + * @param[in] tmrReload Specify timer reload value which need to be set. + * @param[out] None + * @retval E_INVALID_ID The ID passed was invalid,set fail. + * @retval E_OK Set timer counter successful. + * + * @par Description + * @details This function is called to set timer counter and reload value. + ******************************************************************************* + */ +StatusType CoSetTmrCnt(OS_TCID tmrID,U32 tmrCnt,U32 tmrReload) +{ +#if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ + if(tmrID >= CFG_MAX_TMR) + { + return E_INVALID_ID; + } + if( (TmrIDVessel & (1<<tmrID)) == 0) + { + return E_INVALID_ID; + } +#endif + TmrTbl[tmrID].tmrCnt = tmrCnt; /* Reset timer counter and reload value */ + TmrTbl[tmrID].tmrReload = tmrReload; + + if(TmrTbl[tmrID].tmrState == TMR_STATE_RUNNING) /* Is timer running? */ + { + RemoveTmrList(tmrID); /* Yes,reorder timer in timer list */ + InsertTmrList(tmrID); + } + return E_OK; /* Return OK */ +} + + +/** + ******************************************************************************* + * @brief Timer counter dispose + * @param[in] None + * @param[out] None + * @retval None + * + * @par Description + * @details This function is called to dispose timer counter. + ******************************************************************************* + */ +void TmrDispose(void) +{ + P_TmrCtrl pTmr; + + pTmr = TmrList; /* Get first item of timer list */ + while((pTmr != Co_NULL) && (pTmr->tmrCnt == 0) ) + { + if(pTmr->tmrType == TMR_TYPE_ONE_SHOT) /* Is a One-shot timer? */ + { + /* Yes,remove this timer from timer list */ + RemoveTmrList(pTmr->tmrID); + + /* Set timer status as TMR_STATE_STOPPED */ + pTmr->tmrState = TMR_STATE_STOPPED; + (pTmr->tmrCallBack)(); /* Call timer callback function */ + } + else if(pTmr->tmrType == TMR_TYPE_PERIODIC) /* Is a periodic timer? */ + { + /* Yes,remove this timer from timer list */ + RemoveTmrList(pTmr->tmrID); + pTmr->tmrCnt = pTmr->tmrReload; /* Reset timer tick */ + InsertTmrList(pTmr->tmrID); /* Insert timer into timer list */ + (pTmr->tmrCallBack)(); /* Call timer callback function */ + } + pTmr = TmrList; /* Get first item of timer list */ + } +} + + +/** + ******************************************************************************* + * @brief Timer counter dispose in ISR + * @param[in] None + * @param[out] None + * @retval None + * + * @par Description + * @details This function is called to dispose timer counter. + ******************************************************************************* + */ +void isr_TmrDispose(void) +{ + if(OSSchedLock > 1) /* Is schedule lock? */ + { + IsrReq = Co_TRUE; + TimerReq = Co_TRUE; /* Yes,set timer request true */ + } + else + { + TmrDispose(); /* No,call handler */ + } +} + +#endif