FreeRTOS时间管理相关

1、FreeRTOS系统延时函数

  • 系统延时函数有两个:
    如果要使用这两个延时函数,需要在 FreeRTOSConfig.h 中将与其相关的宏定义使能为1:
    FreeRTOS时间管理相关_第1张图片

1、vTaskDelay(); 相对延时
函数参数为:要延时的时钟节拍数,如果时钟节拍为1ms,传入参数值为1000,那延时时间就为1000 * 1ms=1s,相对的,如果时钟节拍为其它值,比如为2ms,那延时时间就为1000 * 2ms=2s。
FreeRTOS时间管理相关_第2张图片
下面贴出相对延时函数源码,源码是我自己复制出来并经过注释的,延时函数基本原理看注释便知,但有效代码无任何删改:

//下面代码只是自己增加了汉字注释,方便直接看代码去理解
#if ( INCLUDE_vTaskDelay == 1 )                     //条件编译,想用这个函数,就要把这个宏置1
void vTaskDelay( const TickType_t xTicksToDelay )
{
    BaseType_t xAlreadyYielded = pdFALSE;

    /* A delay time of zero just forces a reschedule. */
    if( xTicksToDelay > ( TickType_t ) 0U )         //延时节拍数必须大于0,因为不可能为负值嘛~
    {
        configASSERT( uxSchedulerSuspended == 0 );
        vTaskSuspendAll();                          //挂起任务调度器
        {
            traceTASK_DELAY();                      //追踪调试用的,这个不用管,直接忽略

            /* A task that is removed from the event list while the
            scheduler is suspended will not get placed in the ready
            list or removed from the blocked list until the scheduler
            is resumed.

            This task cannot be in an event list as it is the currently
            executing task. */
            prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );//把当前任务添加到延时列表中去,
            //看到这里就大概明白了,FreeRTOS有一个延时列表,有需要延时的任务都会添加到这个列表中去,
            //延时原理大概就是:先把执行延时的任务挂起不再运行,然后将它添加到延时列表,时间到了就
            //再把它恢复出来。
        }
        xAlreadyYielded = xTaskResumeAll();//恢复任务调度
    }
    //下面这些是一些其它机制,总之为的是系统不会出错
    //比如,此任务是否要任务切换之类的,这里先不做深入研究
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }

    /* Force a reschedule if xTaskResumeAll has not already done so, we may
    have put ourselves to sleep. */
    if( xAlreadyYielded == pdFALSE )
    {
        portYIELD_WITHIN_API();
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }
}
#endif /* INCLUDE_vTaskDelay */

2、vTaskDelayUntil(); 绝对延时
绝对延时就是,一个任务里面调用延时函数后,他的总延时节拍数就是函数里面填写的参数值,比如:“vTaskDelayUntil(1000);”,那么这个任务的总延时时间就是这么多,传进去的参数会根据具体执行时间来调整,比较适合与某些需要特定频率周期性执行的任务。

//vTaskDelayUntil()延时函数有两个参数,下面代码注释中有讲解:
//vTaskDelayUntil()延时函数需要用户手动提供一个当前系统节拍的初值
//延时函数根据这个初值来调整具体需要的延时节拍,具体实现过程参见源码这里不深入研究,
//下面贴出自己测试的代码:
void task2_task(void *pvParameters)
{
    TickType_t PreviousWakeTime;//定义一个需要延时的时间
    //但是,函数vTaskDelayUntil()的参数设置的是延时的节拍数,不能直接设置具体时间,
    //这里可使用pdMS_TO_TICKS()函数将时间转换为节拍数:
    const TickType_t TimeIncrement=pdMS_TO_TICKS(50);//将时间转换为节拍数,
    //比如这里要延时50ms,我这里的时钟节拍为1ms,TimeIncrement的值应该还是50
    //经过验证,系统节拍改为2ms,此值变为100,本来以为是25,后续如果需要再做具体研究。
    PreviousWakeTime=xTaskGetTickCount();//获取当前的系统节拍值,在这里是作为初值的
	while(1)
	{
		//任务主体...................................
        printf("%d\r\n",TimeIncrement);//打印"TimeIncrement"值
        vTaskDelayUntil(&PreviousWakeTime,TimeIncrement);//开始延时
        //两个参数中,"PreviousWakeTime"只需要初次使用时手动创建,后续此值会自动更新,无须再管,
        //"TimeIncrement"则是根据自己需要的延时时间,看情况做调整
	}
}


如果看文字代码眼累,下面有绝对延时测试代码截图:
FreeRTOS时间管理相关_第3张图片

2、滴答定时器

不管是什么系统,都需要系统时钟节拍,xTickCount是FreeRTOS的系统时钟节拍计数器,FreeRTOS的节拍与滴答定时器之间的联系纽带就是靠的xTickCount,每个滴答定时器中断xTickCount都会加1,xTickCount的具体操作过程是在:xTaskIncrementTick();中进行的。
滴答定时器的初始化跟以前使用时并无太大区别,主要在于,系统使用这个定时器来完成时钟节拍的实现,是在滴答定时器的中断中实现的;
FreeRTOS时间管理相关_第4张图片

3、FreeRTOS系统时钟节拍

参考本文第2节,如果要深入研究系统节拍,就进入xTaskIncrementTick();函数,翻阅源码。

你可能感兴趣的:(FreeRTOS)