【Freertos】vtaskdelay延时函数

[复制链接]
查看1469 | 回复16 | 2024-3-4 20:48:38 | 显示全部楼层 |阅读模式

前言

裸机开发中,如果要延时,要使用delay等函数(博流使用:bflb_mtimer_delay_ms等函数)

这些函数有个共同点,CPU在延时中是做不了其他东东的,只能延时,CPU的利用率太低了

所以就有了RTOS这种多任务系统

但是,多任务中,有个函数需要延时,怎么处理呢?

这就引入了vtaskdelay函数

首先说明,vtaskdelay(1000) 严格意义上说,这里不是延时1000ms,而是延时1000ticks

心跳速率(tick rate)是FreeRTOS操作系统中的一个重要参数,它决定了系统的时间分辨率和任务调度的频率。每个心跳周期(tick)代表着一个固定的时间片(time slice),任务调度器会根据这个时间片来分配CPU时间给各个任务。

vtaskdelay延时的是时间长度,单位是系统时钟节拍周期

所以,在FreeRTOS中,正常需要延时1ms,需要这样写

vTaskDelay(1000/portTICK_RATE_MS); 

portTICK_RATE_MS常量是用于将毫秒(ms)为单位的时间值转换为以心跳周期(Ticks)为单位的时间值。

这样才是延时1000ms,只是小安派里配置的 1Ticks 等于1ms,所以vTaskDelay(1000); 也是可以的

这是小安派配置文件

#define portSTACK_GROWTH            ( -1 )
#define portTICK_PERIOD_MS          ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#ifdef __riscv64

#define configTICK_RATE_HZ                      ((TickType_t)1000)

正常使用的时候,还可以用这个宏命令转换,也会把毫秒转换成Ticks

pdMS_TO_TICKS( 1000 );

vtaskdelay是如何执行延时的

  • 当vtaskdelay传的值为0的时候,系统会触发一次任务调度,但不会使当前任务进入阻塞状态
  • 如果延时时间大于0,系统会先将当前任务从就绪列表中移除,并将其加入到所谓的"delayed task"链表中。这个过程表示当前任务已经被挂起,并且将在指定的延时时间后恢复执行。
  • 当达到指定的延时时间后,系统会遍历"delayed task"链表,并将所有挂起的任务从链表中移除,然后将其重新加入到就绪列表中。这表示这些任务现在又可以被任务调度器选中并执行了。
  • 在恢复所有挂起的任务后,系统会触发一次任务调度。如果这次调度导致了一个任务切换,那么系统会设置一个标志位,以确保在后续的时钟中断中不再触发任务调度。如果没有发生任务切换,那么系统会再次触发任务调度。

总结

vTaskDelay()函数用于实现任务的阻塞延时,即让出CPU的控制权。在延时期间,任务不会执行任何代码,也不会消耗CPU资源。延时结束后,任务会重新进入就绪状态,等待被任务调度器选中并执行。

本帖被以下淘专辑推荐:

回复

使用道具 举报

WT_0213 | 2024-3-4 21:28:00 | 显示全部楼层
回复

使用道具 举报

lazy | 2024-3-5 09:23:50 | 显示全部楼层
回复

使用道具 举报

干簧管 | 2024-3-5 09:25:21 | 显示全部楼层
👍
回复

使用道具 举报

曹县 | 2024-3-5 09:36:48 | 显示全部楼层
回复

使用道具 举报

wukong50 | 2024-3-5 10:15:29 | 显示全部楼层
回复

使用道具 举报

1084504793 | 2024-3-5 10:36:59 | 显示全部楼层
回复

使用道具 举报

timo | 2024-3-5 12:19:07 | 显示全部楼层
回复

使用道具 举报

物联网 | 2024-3-5 13:07:37 | 显示全部楼层
赞一下
回复

使用道具 举报

1055173307 | 2024-3-5 13:19:33 | 显示全部楼层
有意思
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则