freeRTOS相对延时函数-vTaskDelay源码分析

这篇博客详细分析了FreeRTOS中的vTaskDelay函数,该函数用于任务延时。作者首先介绍了函数的基本逻辑,包括挂起调度器、将当前任务添加到延时列表以及恢复调度器的过程。在添加任务到延时列表时,考虑了任务是否被挂起、延时周期计算以及可能的溢出情况。通过对源码的解析,帮助读者理解FreeRTOS的任务调度机制。

最近学习白问网韦东山老师在B站开源的freeRTOS课程,网址:韦东山直播公开课:RTOS实战项目之实现多任务系统 第1节:裸机程序框架和缺陷_哔哩哔哩_bilibili和7天物联网训练营【第2期】7天物联网智能家居实战训练营

在学习过程中按照韦老师的方法分析了下freeRTOS源码,如果有不对的地方请指证。
 

vTaskDelay源码分析,基于cubemx生成的freeRTOS工程。

	void vTaskDelay( const TickType_t xTicksToDelay )
	{
	//xAlreadyYielded:已经调度的状态
	//初始赋值为0 
	BaseType_t xAlreadyYielded = pdFALSE;

		/* 延时周期是否大于0,不大于0,就不应该调度 */
		if( xTicksToDelay > ( TickType_t ) 0U )
		{
			configASSERT( uxSchedulerSuspended == 0 );
			//1、挂起调度器
			vTaskSuspendAll();
			{
				traceTASK_DELAY();

				/* 1、添加任务到延时列表中
				   2、需要传入两个参数
					2.1、xTicksToDelay:延时周期
					2.2、pdFALSE:状态值为0


				*/
				prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
			}
			//恢复调度器,这个调度器是有返回值的,这返回值,表示在恢复调度器
			的时候,是否已经进行了任务切换
			xAlreadyYielded = xTaskResumeAll();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}

		/* xAlreadyYielded 等于FALSE,代表在恢复调度器的时候,没有进行任务切换 */
		if( xAlreadyYielded == pdFALSE )
		{
			//调用了任务切换:内部就是
### vTaskDelay 函数详细介绍 在 FreeRTOS 中,`vTaskDelay` 函数用于使当前任务进入阻塞状态,直到指定的时间段过去,是一种相对延时方式,即从执行 `vTaskDelay` 函数开始,直到指定延时的时间结束 [^1][^4]。其参数以“滴答数”(tick)为单位,滴答数由系统时钟决定。系统滴答时间是 FreeRTOS 内核的时间基准,由 `configTICK_RATE_HZ` 宏定义,表示每秒钟的滴答次数 [^4]。 ### vTaskDelay 函数使用方法 `vTaskDelay` 函数的原型如下: ```c void vTaskDelay( const TickType_t xTicksToDelay ); ``` 其中,`xTicksToDelay` 是需要延时的滴答数。 以下是一个简单的使用示例: ```c #include "FreeRTOS.h" #include "task.h" // 任务函数 void vTaskFunction( void *pvParameters ) { for( ;; ) { // 任务逻辑 // 延时 1000 个滴答 vTaskDelay( 1000 ); } } int main( void ) { // 创建任务 xTaskCreate( vTaskFunction, "Task", 1000, NULL, 1, NULL ); // 启动调度器 vTaskStartScheduler(); // 如果调度器启动失败,程序会执行到这里 for( ;; ); } ``` 在上述示例中,任务函数 `vTaskFunction` 会周期性地执行,每次执行完任务逻辑后,会调用 `vTaskDelay(1000)` 使任务进入阻塞状态,延时 1000 个滴答。 ### vTaskDelay 函数源码分析 `vTaskDelay` 函数源码如下 [^2]: ```c void vTaskDelay( const TickType_t xTicksToDelay ) { BaseType_t xAlreadyYielded = pdFALSE; if( xTicksToDelay > ( TickType_t ) 0U ) { configASSERT( uxSchedulerSuspended == 0 ); vTaskSuspendAll(); { traceTASK_DELAY(); prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE ); } xAlreadyYielded = xTaskResumeAll(); } else { mtCOVERAGE_TEST_MARKER(); } if( xAlreadyYielded == pdFALSE ) { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } } ``` 当 `xTicksToDelay` 大于 0 时,会先调用 `vTaskSuspendAll` 挂起所有任务,然后将当前任务加入到延时列表中,最后调用 `xTaskResumeAll` 恢复所有任务。如果 `xTicksToDelay` 等于 0,则不会进行延时操作。 ### 注意事项 在使用 `vTaskDelay` 函数时,需要确保任务调度器已经启动。如果在任务调度器启动之前调用 `vTaskDelay` 函数,由于此时没有任务创建和运行,无法进行延时函数里面的任务阻塞,会导致问题 [^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值