liteos中的timer相关的API主要有创建一个定时任务,刚创建时这个定时任务并没有启动,需要丢用另一个API LOS_SwtmrStart来启动这个timer。具体举例如下:
UINT32 Example_swTimer(VOID)
{
UINT16 id1;
UINT16 id2;// timer id
UINT32 uwRet = LOS_OK;
#创建一个定时任务,这个定时任务的运行周期是1000,回调函数是Timer1_Callback,
uwRet = LOS_SwtmrCreate(1000, LOS_SWTMR_MODE_ONCE, Timer1_Callback, &id1, 1);
if (LOS_OK != uwRet)
{
dprintf("create Timer1 failed\n");
}
else
{
dprintf("create Timer1 success\n");
}
#根据LOS_SwtmrCreate 返回的id1 来启动这个timer
uwRet = LOS_SwtmrStart(id1);
if (LOS_OK != uwRet)
{
dprintf("start Timer1 failed\n");
}
else
{
dprintf("start Timer1 sucess\n");
}
#延迟200
(VOID)LOS_TaskDelay(200);
#停止这个timer
uwRet = LOS_SwtmrStop(id1);
if (LOS_OK != uwRet)
{
dprintf("stop Timer1 failed\n");
}
else
{
dprintf("stop Timer1 sucess\n");
}
return LOS_OK;
}
下来我们先看看创建定时任务的函数LOS_SwtmrCreate
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 uwInterval, UINT8 ucMode, SWTMR_PROC_FUNC pfnHandler, UINT16 *pusSwTmrID, UINT32 uwArg
)
{
SWTMR_CTRL_S *pstSwtmr;
UINTPTR uvIntSave;
uvIntSave = LOS_IntLock();
if (NULL == m_pstSwtmrFreeList)
{
LOS_IntRestore(uvIntSave);
return LOS_ERRNO_SWTMR_MAXSIZE;
}
#可以看到所有timer的都是添加到m_pstSwtmrFreeList这个列表中,这个列表是在osSwTmrInit中通过LOS_MemAlloc来申请
#空间并赋初值,剩下主要就是给pstSwtmr赋初值
pstSwtmr = m_pstSwtmrFreeList;
m_pstSwtmrFreeList = pstSwtmr->pstNext;
LOS_IntRestore(uvIntSave);
pstSwtmr->pfnHandler = pfnHandler;
pstSwtmr->ucMode = ucMode;
pstSwtmr->uwInterval = uwInterval;
pstSwtmr->pstNext = (SWTMR_CTRL_S *)NULL;
pstSwtmr->uwCount = 0;
pstSwtmr->uwArg = uwArg;
pstSwtmr->ucState = OS_SWTMR_STATUS_CREATED;
*pusSwTmrID = pstSwtmr->usTimerID;
return LOS_OK;
}
到这里周期性任务就创建好了,可以知道所有的周期性任务都是添加到m_pstSwtmrFreeList这个全局的list中。
创建完周期性任务后,就可以通过LOS_SwtmrStart 来开始运行这个timer
LITE_OS_SEC_TEXT VOID osSwTmrStart(SWTMR_CTRL_S *pstSwtmr)
{
SWTMR_CTRL_S *pstPrev = (SWTMR_CTRL_S *)NULL;
SWTMR_CTRL_S *pstCur = (SWTMR_CTRL_S *)NULL;
pstSwtmr->uwCount = pstSwtmr->uwInterval;
pstCur = m_pstSwtmrSortList;
#根据到期时间将周期性任务插入到另外一个全局性列表中m_pstSwtmrSortList
#从这里可以知道这个链表中的周期性任务都是按照到期时间严格排序
while (pstCur != NULL)
{
if (pstCur->uwCount > pstSwtmr->uwCount)
{
break;
}
pstSwtmr->uwCount -= pstCur->uwCount;
pstPrev = pstCur;
pstCur = pstCur->pstNext;
}
#设置这个周期性任务的状态为运行
pstSwtmr->ucState = OS_SWTMR_STATUS_TICKING;
return;,这是一个
}
那具体是谁来调用m_pstSwtmrSortList中的周期性任务呢?
最后是在osSwtmrScan来调用的,而osSwtmrScan是由osTickHandler。这个是时间戳的中断函数,我们重点看看osSwtmrScan
LITE_OS_SEC_TEXT UINT32 osSwtmrScan(VOID)
{
if (m_pstSwtmrSortList != NULL)
{
#到期时间自检,为零后,标志对应的周期事件到期,调用osSwTmrTimeoutHandle来执行回调函数
if (--(m_pstSwtmrSortList->uwCount) == 0)
{
osSwTmrTimeoutHandle();
}
}
return LOS_OK;
看看osSwTmrTimeoutHandle的实现
LITE_OS_SEC_TEXT static VOID osSwTmrTimeoutHandle(VOID)
{
SWTMR_CTRL_S *pstSwtmr = m_pstSwtmrSortList;
SWTMR_HANDLER_ITEM_S stSwtmrHandler;
while (pstSwtmr != NULL && pstSwtmr->uwCount == 0)
{
m_pstSwtmrSortList = pstSwtmr->pstNext;
#得到本次到期的周期事件的回调函数和参数
stSwtmrHandler.pfnHandler = pstSwtmr->pfnHandler;
stSwtmrHandler.uwArg = pstSwtmr->uwArg;
#开始执行本次到期事件的回调函数,这里将到期事件转成一个task,放到queue中运行
(VOID)LOS_QueueWriteCopy(m_uwSwTmrHandlerQueue, &stSwtmrHandler, sizeof(SWTMR_HANDLER_ITEM_S), LOS_NO_WAIT);
#根据这个周期时间是period还是onshot 来处理
if (pstSwtmr->ucMode == LOS_SWTMR_MODE_ONCE)
{
osSwtmrDelete(pstSwtmr);
if (pstSwtmr->usTimerID < OS_SWTMR_MAX_TIMERID - LOSCFG_BASE_CORE_SWTMR_LIMIT)
pstSwtmr->usTimerID += LOSCFG_BASE_CORE_SWTMR_LIMIT;
else
pstSwtmr->usTimerID %= LOSCFG_BASE_CORE_SWTMR_LIMIT;
}
else if ( pstSwtmr->ucMode == LOS_SWTMR_MODE_PERIOD)
{
osSwTmrStart(pstSwtmr);
}
else if (pstSwtmr->ucMode == LOS_SWTMR_MODE_NO_SELFDELETE)
{
pstSwtmr->ucState = OS_SWTMR_STATUS_CREATED;
}
pstSwtmr = m_pstSwtmrSortList;
}
}
}