要使用定时器必须创建定时器任务。
//如果没有创建好列表,就创建一个
prvCheckForValidListAndQueue();
{
定时器列表中存储创建的定时器,如果定时时间超过当前最大时间,就放入溢出列表。
pxCurrentTimerList = &xActiveTimerList1;
pxOverflowTimerList = &xActiveTimerList2;
动态创建一个定时器队列
xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );
vQueueAddToRegistry( xTimerQueue, "TmrQ" );///这一步不知道用处是什么。
}
//进入定时器任务。
static void prvTimerTask( void *pvParameters )
{
TickType_t xNextExpireTime;
BaseType_t xListWasEmpty;
for( ;; )
{
/* Query the timers list to see if it contains any timers, and if so,
obtain the time at which the next timer will expire. */
//获取下一个定时的时间,即如果定时10ms,则在启动定时器的时间加上10ms,即定时时间。如果没有定时器存在,则返回0,否则返回具体的值
xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty );
/* If a timer has expired, process it. Otherwise, block this task
until either a timer does expire, or a command is received. */
prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty );解析1
/* Empty the command queue. */
prvProcessReceivedCommands();
}
}
解析1
进入prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty );
{
获取当前的时间,并判断定时器列表有没有交换,如果定时器计时超过一个周期就会从0开始,意味着需要交换定时器列表。
xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
不考虑其它问题交换列表 pxTemp = pxCurrentTimerList;
pxCurrentTimerList = pxOverflowTimerList;
pxOverflowTimerList = pxTemp;
不需要交换列表时。
if( xTimerListsWereSwitched == pdFALSE )
{
定时器达到时间。
if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )
{
( void ) xTaskResumeAll();
prvProcessExpiredTimer( xNextExpireTime, xTimeNow );解析2
}
没有定时器达到时间
else{
if( xListWasEmpty != pdFALSE )//判断定时器列表是不是空的
{
/* The current timer list is empty - is the overflow list
also empty? */
是空的再判断溢出列表是不是空的
· 如果都是空的那么xListWasEmpty=1;
xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList );
}
vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty );解析3
这个函数的Restricted的作用不明白,
}
}
}
解析2
prvProcessExpiredTimer( xNextExpireTime, xTimeNow );
{
如果是单次定时
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
判断是否是周期性的定时
if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )
{
/* The timer is inserted into a list using a time relative to anything
other than the current time. It will therefore be inserted into the
correct list relative to the time this task thinks it is now. */
将定时器插入到定时器列表,
if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE )
{
/* The timer expired before it was added to the active timer
list. Reload it now. */
插入成功,就会发送命令,再次启动。
xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );
configASSERT( xResult );
( void ) xResult;
}
}
/* Call the timer callback. */
pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
这是定时器的回调函数,pxCallbackFunction是函数指针,参数是定时器句柄。我们在创建定时器时传递。
}
解析3
void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
{
vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely );
}
void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
{
vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
将当前任务的事件项插入到&( pxQueue->xTasksWaitingToReceive )列表
if( xWaitIndefinitely != pdFALSE )//如果没有定时器任务,那么进入挂起态
{
xTicksToWait = portMAX_DELAY;
}
traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );//将等待时间设为最大值,即永远阻塞,直到被唤醒。(会被挂起。)
}
}