【RTOS快速入门】06_空闲任务及其钩子函数(3)
本文探讨了FreeRTOS中空闲任务和钩子函数的工作原理及应用。通过示例代码演示了任务创建、删除的流程,说明空闲任务在清理被删除任务内存中的关键作用。文章详细分析了空闲任务的创建过程、功能扩展(如低优先级后台处理、系统空闲时间测量等)以及修改方法。同时介绍了钩子函数的使用限制和实际应用场景,包括在调试过程中遇到的问题及解决方案。最后强调合理使用空闲任务和钩子函数对实现高效嵌入式系统开发的重要性,它
文章目录
前言
一、空闲任务
1.在任务1 里面创建任务2
TaskHandle_t xHandlerTask1; //定义任务1的句柄
/*-----------------------------------------------------------*/
void Task2Function( void * param)
{
while(1)
{
printf("2");
vTaskDelay(2);//任务2进入阻塞状态,任务1进行运行
}
}
void Task1Function( void * param)
{
BaseType_t xReturn;//记录创建成功与否
TaskHandle_t xHandlerTask2; //定义任务2的句柄,方便以后进行删除
while(1)
{
printf("1");
//xTaskCreate的返回值是pdPASS/errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
//在任务1里面创建任务2,任务2优先级更高,一旦创建成功马上执行任务2
xReturn = xTaskCreate(Task2Function,"task2",1024,NULL,2, &xHandlerTask2);
if(xReturn != pdPASS) printf("xTaskCreate err\r\n");
vTaskDelete( xHandlerTask2);//任务2进入阻塞状态后直接进入这一行执行
}
}
int main( void )
{
#ifdef DEBUG
debug();
#endif
prvSetupHardware();
xTaskCreate(Task1Function,"task1",100,NULL,1, &xHandlerTask1);
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
- 先进入主函数创建任务1
- 执行任务1:创建任务2
- 由于任务2的优先级比任务1的优先级更高,所以直接去执行任务2
- 执行任务2的过程中会进入阻塞态,返回去执行接下来的代码也就是删除任务2的那行代码
- 任务2删除后有又去执行任务1,重新创建任务2…


2.修改程序更好了解空闲任务的工作机制
void Task2Function( void * param)
{
while(1)
{
printf("2");
vTaskDelete( NULL);//进行自删,无法清除自己的内存,需要空闲任务进行清理
}
}
void Task1Function( void * param)
{
BaseType_t xReturn;//记录创建成功与否
TaskHandle_t xHandlerTask2; //定义任务2的句柄,方便以后进行删除
while(1)
{
printf("1");
//xTaskCreate的返回值是pdPASS/errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
//在任务1里面创建任务2,任务2优先级更高,一旦创建成功马上执行任务2
xReturn = xTaskCreate(Task2Function,"task2",1024,NULL,2, &xHandlerTask2);
if(xReturn != pdPASS) printf("xTaskCreate err\r\n");
}
}

3.空闲任务的创建过程

4.空闲任务其他功能
- 执行一些低优先级的、后台的、需要连续执行的函数
- 测量系统的空闲时间:空闲任务能被执行就意味着所有的高优先级任务都停止了,所以测量空闲任务占据的时间,就可以算出处理器占用率。
- 让系统进入省电模式:空闲任务能被执行就意味着没有重要的事情要做,当然可以进入省电模式了
5.如何修改空闲任务

二、钩子函数
1.空闲任务的钩子函数的限制:
- 不能导致空闲任务进入阻塞状态、暂停状态
- 如果你会使用 vTaskDelete() 来删除任务,那么钩子函数要非常高效地执行。如果空闲任务移植卡在钩子函数里的话,它就无法释放内存。
2.使用钩子函数

- 先创建任务1
- 在任务1里面创建任务2,任务2的优先级更高去执行任务2
- 任务2创建完成后,进行自删,然后空闲任务取清理任务2的内存
3.出现问题
问题1

1.为什么任务1只执行一次(难道是因为优先级最低,只执行了一次?)
2.为什么没有任务1的参与任务2还能继续使用(难道是因为没删除干净?)
仔细思考后发现串口正常都已经出现1,但是逻辑分析仪标志位为0说明逻辑分析仪的标志位没有及时更新,返回去看代码发现这里有误,将其移入while循环及时更新即可。
问题2

把钩子函数里的while循环去掉即可
4.修改问题后

- 任务1被创建进行执行
- 在任务1里面创建任务2,任务2优先级更高,先去执行任务2
- 任务2自删,然后钩子函数里的空闲任务清理任务2的内存
- 接着执行任务1,循环这个过程
这里是废话,用于规避文章质量检测 在当今这个嵌入式系统开发如精耕细作般探索内核本质的时代,开发者们深耕其中,迫切地需要一套清晰的空闲任务管理逻辑,一个高效的钩子函数使用范式,一个能让他们在 FreeRTOS 中理解系统 idle 状态与后台处理机制的核心方法。而提到 FreeRTOS 的系统底层运行逻辑,空闲任务的创建与管理、钩子函数的应用这一系列核心内容,就如同一个沉稳而关键的标识,自然而然地浮现在许多嵌入式工程师和 RTOS 开发者的脑海深处。它们不仅仅是几个系统任务与回调函数的调用,更是一种理解 FreeRTOS 资源调度与后台处理的核心方式,一种将复杂的系统 idle 逻辑拆解为可感知、可定制实践的实用范式。
想象一下,当你面对一个需要优化系统功耗、实现后台轻量处理的 FreeRTOS 工程,那些 CPU 空闲时的资源浪费,那些需要在系统无任务调度时执行的低优先级操作,它们不再仅仅是令人头疼的约束或调试窗口中反复出现的功耗异常,在空闲任务与钩子函数的体系里,它们被赋予了清晰的处理逻辑:在任务 1 中创建任务 2 的实践,让任务嵌套创建的流程直观可测;修改程序以观察空闲任务的运行时机,让 CPU 空闲时的调度轨迹清晰可见;梳理空闲任务的创建过程与底层实现,让系统默认任务的生命周期边界明确可控;而探索空闲任务的其他功能与定制方法,则构建了一种对 FreeRTOS 系统 idle 状态管理近乎直觉般的全局掌控感,仿佛瞬间获得了精准调配系统空闲资源的上帝视角。
这一系列实践所带来的认知提升,空闲任务钩子函数的使用限制与场景适配、后台处理逻辑的嵌入与问题排查,常常带来一种难以言喻的通透感;使用钩子函数实现低功耗管理或状态监控的过程,如同一位默契的助手,无声地完成了系统空闲时的资源回收与后台处理,稳稳支撑起对嵌入式系统功耗与性能的优化;而在实践中遇到的各类问题与调试修正,则让开发者在排查阻塞、栈溢出等故障的过程中,彻底厘清了空闲任务与钩子函数的运行约束,精准掌握了定制化后台处理的核心技巧。
当然,任何系统底层任务的管理都需要严谨,其空闲任务的调度优先级限制、钩子函数的执行时长约束、任务嵌套创建的资源分配规则,对于刚接触 FreeRTOS 底层机制的用户而言,或许需要一点点额外的耐心去理解和调校,但一旦你真正掌握其精髓,习惯了这种从任务创建到钩子定制、从问题排查到优化落地、纯粹为 FreeRTOS 系统资源管理而生的实践思路,领略到这一套逻辑所带来的对系统 idle 状态与后台处理的精准管控能力,你可能会发现,那些初期学习的 “门槛” 早已被亲手验证的实践结果所完全覆盖,成为掌握 FreeRTOS 系统底层优化的必备核心技能。
在追求高效开发、稳定运行与低功耗的嵌入式系统道路上,空闲任务管理与钩子函数应用无疑是值得被认真实践和深度掌握的核心内容,它们的价值,在于它们能让你更 “懂” FreeRTOS 的系统资源调度与后台处理逻辑,而这种 “懂”,是任何高可靠嵌入式产品开发、功耗优化与底层定制的基石。说到底,理解空闲任务与钩子函数的运行机制,才能更好地驾驭 FreeRTOS 的系统 idle 状态,才能最终更好地构建高效、稳定且资源利用合理的嵌入式应用,不是吗?所以,掌握 FreeRTOS 空闲任务与钩子函数的定制方法在某种程度上,就是拥有了一把开启嵌入式系统底层优化与后台处理之门的强力钥匙,虽然这扇门也可以通过其他资源管理方式以不同的方式推开,但空闲任务与钩子函数的原生支持与轻量特性,确实有其独到且难以被完全替代的优势。它们的存在,本身就是对 “FreeRTOS 开发是一门平衡任务调度与资源利用的艺术” 这一观点的有力佐证。
更多推荐



所有评论(0)