freertos定时器任务运行流程()

要使用定时器必须创建定时器任务。

//如果没有创建好列表,就创建一个

    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 );//将等待时间设为最大值,即永远阻塞,直到被唤醒。(会被挂起。)

    }

}

你可能感兴趣的:(Freertos,linux,运维,服务器)