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

        }

    }

  • 相关阅读:
    基于多块信息提取和马氏距离的k近邻故障监测
    深入理解操作系统-进程篇
    关于JVM的一些问题
    算法学习笔记Day8——回溯算法
    uniapp 在 onLoad 事件中 this.$refs 娶不到的问题
    MetaTown:一个可以自己构建数字资产的平台
    PyTorch主要组成模块 | hook函数 | 正则化weight decay与Dropout | 标准化
    多模态预训练模型指北——LayoutLM
    Python进阶——Socket编程
    越早报考RFP是不是越好?原因是什么?
  • 原文地址:https://blog.csdn.net/m0_54797575/article/details/133461532