【任务管理与调度机制---vTaskSuspendAll函数源码详解】
vTaskSuspendAll() 是 FreeRTOS 中的一个重要函数,用于挂起任务调度器。
·
概要
vTaskSuspendAll() 是 FreeRTOS 中的一个重要函数,用于挂起任务调度器。下面从源码角度详细解析这个函数。
函数功能
vTaskSuspendAll() 的主要作用是挂起任务调度器,但它不会禁用中断。在调度器挂起期间:
- 不会发生任务切换
- 可以安全地访问共享资源(无需额外互斥锁)
- 中断服务程序仍然可以执行
源码解析
- 函数定义
/* 在 task.c 中 */
void vTaskSuspendAll( void )
{
/* 增加调度器挂起计数 */
++uxSchedulerSuspended;
}
- 关键数据结构
/* 在 task.c 中声明的全局变量 */
#if ( INCLUDE_xTaskGetSchedulerState == 1 )
/* 调度器挂起计数器 */
volatile BaseType_t uxSchedulerSuspended = ( BaseType_t ) pdFALSE;
#else
/* 很多编译器会对没有引用的静态变量发出警告 */
static volatile BaseType_t uxSchedulerSuspended = ( BaseType_t ) pdFALSE;
#endif
- 工作原理
调度器挂起计数器
1)uxSchedulerSuspended 是一个计数器(不是简单的布尔值)
2)值为 0 表示调度器正常运行
3)值大于 0 表示调度器被挂起
4)使用计数器而不是布尔值,允许函数嵌套调用
相关函数调用
/* 挂起调度器 */
vTaskSuspendAll();
/* 执行临界区操作(无任务切换) */
// ... 你的代码 ...
/* 恢复调度器 */
xTaskResumeAll();
- 如何阻止任务切换
调度器的挂起主要通过影响以下地方来实现:
1) 在 xTaskIncrementTick() 中:
BaseType_t xTaskIncrementTick( void )
{
/* ... 前面的代码 ... */
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
/* 只有在调度器未挂起时才检查任务切换 */
if( xYieldPending != pdFALSE )
{
xSwitchRequired = pdTRUE;
}
}
/* ... 后面的代码 ... */
}
2) 在 xTaskResumeAll() 中(恢复函数):
BaseType_t xTaskResumeAll( void )
{
/* 减少挂起计数 */
--uxSchedulerSuspended;
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
/* 如果计数为0,可能需要处理累积的tick */
/* 并检查是否需要任务切换 */
if( xPendedTicks > ( TickType_t ) 0U )
{
/* 处理挂起期间积累的tick */
}
/* 检查是否需要任务切换 */
if( xYieldPending != pdFALSE )
{
xSwitchRequired = pdTRUE;
}
}
}
- 注意事项
1)不可递归:虽然使用计数器支持嵌套,但需确保每个 vTaskSuspendAll() 都有对应的 xTaskResumeAll()
2)中断处理:
中断仍然会发生
中断服务程序可以调用 FreeRTOS API
但不会发生任务切换,直到调度器恢复
3)时间管理:
在调度器挂起期间,系统 tick 中断仍然发生
tick 计数会被累积,在恢复时处理 - 性能考虑
1)vTaskSuspendAll() 执行非常快(只是增加计数器)
2)比使用互斥锁开销小
3)适合保护较长的临界区代码
4)不适合需要中断同步的场景(此时应用 taskENTER_CRITICAL())
总结
vTaskSuspendAll() 是一个轻量级的调度器挂起机制,通过简单的计数器管理来实现。它提供了在不需要任务切换的场景下安全访问共享资源的能力,同时保持了中断响应的能力。使用时需要注意正确的嵌套和恢复,以避免系统死锁或性能问题。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐
所有评论(0)