FreeRTOS学习笔记之时间片

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

一、时间片?

多个任务拥有相同的任务优先级,当此时当前任务优先级下的任务进入运行态时,这几个任务轮流享有CPU使用时间,任务调度允许一个任务运行一个时间片后让出CPU使用权给同优先级的任务,如此反复。

二、配置

使用时间片调度的话宏configUSE_PREEMPTION和宏configUSE_TIME_SLICING必须为1.
一个时间片的长度由configTICK_RATE_HZ配置,一个时间片的长度就是一个滴答定时器的中断周期。

例:
configTICK_RATE_HZ=1000
时间片长度为1ms

时间片任务调度发生在滴答定时器的中断服务函数中,SysTick_Handler()中会调用可以出发任务调度的函数xPortSysTickHandler()

void xPortSysTickHandler( void )
{
	vPortRaiseBASEPRI();
	{
		/* Increment the RTOS tick. */
		if( xTaskIncrementTick() != pdFALSE )
		{
			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
		}
	}
	vPortClearBASEPRIFromISR();
}

这里有一个条件: xTaskIncrementTick() != pdFALSE满足才能触发任务调度

BaseType_t xTaskIncrementTick( void )
{
TCB_t * pxTCB;
TickType_t xItemValue;
BaseType_t xSwitchRequired = pdFALSE;
	traceTASK_INCREMENT_TICK( xTickCount );
	if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
	{

		#if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) 	 
		{
			if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) 
			> ( UBaseType_t ) 1 )       		  
			{
				xSwitchRequired = pdTRUE;                      
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		#endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */

	························
	#endif /* configUSE_PREEMPTION */

	return xSwitchRequired;
}

#if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
上述两个宏,少一个都不会编译
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
判断当前任务优先级下是否还有其他任务,如果有就返回pdTRUE,触发任务调度。

三、解释

configTICK_RATE_HZ它配置了滴答定时器的中断周期
滴答定时器一般是用来做延时函数
另外,可以做操作系统的心跳节拍,根据“心跳”的节拍来工作,把整个时间段分成很多小小的时间片。
配置滴答定时器和单条语句的执行没有太多关系。
vTaskDelay延时N个时间片,这是个相对延时

四、延时

相对延时

从调用vTaskDelay开始延时多长时间,相当于裸机中的delay,延时时间是从调用这个函数开始的。
如果调用vTaskDelay()函数的任务在执行过程中被更高优先级的任务或者中断所打断,那么调用vTaskDelay()函数的任务将会受到影响,此时将不能保持一个固定的时间间隔运行。

绝对延时

调用vTaskDelayUntil()函数时,绝对延时的时间包含该任务本身的执行时间,以及任务被打断的时间。
即从第一次开始任务x,到第二次开始任务x,中间的时间间隔就是设置的延时长度。

void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );

pxPreviousWakeTime:指针,指向一个变量,该变量保存任务最后一次解除阻塞的时间。第一次使用前,该变量
					必须初始化为当前时间。之后这个变量会在vTaskDelayUntil()函数内自动更新。
xTimeIncrement :绝对延时时间,即任务重复执行的时间间隔。

例:

static portTickType xlastwaketime;

vTaskDelayUntil(&xlastwaketime,N);

区别

相对延时的时间不会包含任务本身的执行时间和任务被打断的时间,绝对延时的时间则会包含任务本身的执行时间和任务被打断的时间,这一点是两种延时函数之间的重要区别。

注:

如果任务延时过程中被打断的时间太长,回来之后延时都超过了,那么则会立马执行程序,不会再执行延时操作(任务不会再阻塞延时)。

如果vTaskDelayUntil()函数的任务优先级并非最高级,那么该任务可能被中断或者更高优先级的任务打断,若此时延时时间到了该任务将处于就绪态,但无法保证该任务能够马上执行。

上述的情况两个函数都有可能遇到,即使是vTaskDelayUntil也没有办法保证延时时间一定准确,实际项目还需要借助Tracealyzer等RTOS可视化分析工具进行分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值