钩子函数的类型:
1.空闲任务钩子函数(Idle Task Hook)
首先解释一下什么是空闲任务:是由内核自动创建(启动调度器vTaskStartScheduler()会自动创建)的系统任务,不是用户手动编写的。
空闲任务的作用:在没有其他任务运行的时候会执行一些优先级低(0级)的后台操作(内存清理、进入低功耗、还可以避免无任务可调度时发生的死锁)
空闲任务的特点是:一个无限循环的过程,不断调用prvIdleTask() 函数
空闲任务钩子函数的开启方式和作用:
1.在FreeRTOSConfig.h中,将configUSE_IDLE_HOOK对应的宏定义配置为1。
2.实现 vApplicationIdleHook() 函数
作用:指向低优先级后台任务。
2.Tick钩子函数(Tick Hook)
在FreeRTOS中,Tick钩子函数是一个用户自定义的函数,它的作用时间是:每次系统时间节拍中断(由SyeTick定时器或硬件定时器(STM32的TIMx)周期性触发,为操作系统提供时间基准)的时候会被调用。
系统时间节拍中断的作用:
1.驱动任务调度:检查是否有任务需要切换(如时间片轮询或延迟到期)。
2.维护系统时间:更新 xTickCount(系统运行的总 Tick 数)。
3.实现超时机制:如 vTaskDelay()、xQueueSend() 的超时等待。
Tick钩子函数的开启方式和作用:
1.在FreeRTOSConfig.h中,将configUSE_TICK_HOOK对应的宏定义配置为1。
2.实现vApplicationTickHook()函数(这部分函数的内容是由用户自定义的)
作用发生于:在系统时钟节拍(Tick)中断中调用;在xTaskIncrementTick() 函数内部,即 FreeRTOS 更新系统时间和检查任务延迟列表时
用途:
1.适用于需要严格周期性执行且对时间敏感的任务如( PWM 信号生成、ADC采样),比软件定时器(xTimer)更精确,因为它在Tick中断中直接执行,不受任务调度影响。
2.还用于系统性能检测上:如统计 CPU 使用率、任务执行时间等,可以记录 Tick 计数,用于计算任务运行时间占比。
3.实时调试:在Tick 中断中打印调试信息,不影响任务调度;可以检查任务堆栈使用情况、任务状态等。
4.硬件外设的周期控制:控制 DAC、步进电机等需要严格时序的设备;比任务循环 + vTaskDelay() 更精确
限制使用情况:
1.不能调用阻塞式 API(如 vTaskDelay(), xQueueSend()),否则会导致系统崩溃。
2.执行时间必须短,在中断的上下文运行,不能使用浮点运算。
补充一点:节拍频率是可自定义的(在FreeRTOSConfig.h中的#define configTICK_RATE_HZ 1000 ),该定义的值决定了中断频率,频率越大,间隔时间越短,任务调度越及时,cpu开销越大。
3.内存分配失败钩子函数(Malloc Failed Hook)
内存分配失败钩子函数的作用:当动态内存分配失败时(pvPortMalloc() 返回 NULL)自动调用,用于处理内存不足的情况。
配置方式:
1.在FreeRTOSConfig.h中将宏定义#define configUSE_MALLOC_FAILED_HOOK配置为1.
2.实现 vApplicationMallocFailedHook()函数(可用户自定义的回调函数)。
3.调用钩子函数之后,可选择系统复位或者释放预留内存。
触发的典型场景:
1.任务创建失败(xTaskCreate() 返回 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)。
2.队列/信号量创建失败(xQueueCreate() 返回 NULL)。
3.直接调用 pvPortMalloc() (该函数是动态内存分配函数),分配内存失败。
4.任务栈溢出钩子函数(Stack Overflow Hook)
任务栈溢出钩子函数的作用:检测任务栈的溢出(需要配合栈检查机制),并在溢出发生的时候触发用户自定义的处理逻辑(记录错误、复位系统)。
配置方式:
1.在FreeRTOSConfig.h中将宏定义的#define configCHECK_FOR_STACK_OVERFLOW配置为1或2。
2.实现vApplicationStackOverflowHook()函数(完全由用户自定义)
为什么此处的宏定义可以为1或者2,原因如下:
FreeRTOS提供两种栈溢出的检测方式,可通过宏定义进行选择。
模式1:在任务切换时检查栈指针是否超出有效范围。(检测速度快、开销少,但只能检测严重溢出(指针已完全越界)。)
模式2:在任务创建时填充栈空间魔数(如 0xA5A5A5A5),并在切换时检查是否被修改。(能检测轻微溢出(如栈写穿了但指针未越界),开销大)
一般默认模式1,需要精度的时候才选模式2。
栈溢出的时候,可选择下面的方式进行处理:
1.记录错误信息。
2.复位系统(紧急回复)
3.挂起出错任务。
为了避免这类情况的发生的,我们一般在分配栈的大小的时候就需要注意,并且要避免大局部的变量(尽量用动态分配或者是静态数组),再者我们可使用FreeRTOS的栈使用统计功能(会返回剩余的栈空间最小值),进行监测。
5.守护任务(Daemon Task)启动钩子函数
守护任务(Daemon Task)启动钩子函数的作用:在RTOS守护任务(如定时器服务任务、IDLE任务的清理任务)启动前调用。
配置方式:
1.在FreeRTOSConfig.h中将宏定义的#define configUSE_DAEMON_TASK_STARTUP_HOOK配置为1.
2.实现vApplicationDaemonTaskStartupHook()函数(完全由用户自定义的)。
该钩子函数运行场景:
1.在守护任务运行前执行初始化代码(如初始化外设、配置硬件资源)。
2.监控或调试守护任务的启动过程。
3.动态调整守护任务的优先级或栈大小(需结合 FreeRTOS API)
6. 任务创建/删除钩子函数(可选)
任务创建/删除钩子函数的作用:任务创建(调用xTaskCreate()或xTaskCreateStatic()成功时触发)或删除(调用vTaskDelete()删除任务时触发(包括任务自我删除))时触发,用于资源跟踪。
配置方式:
1.在FreeRTOSConfig.h中启用Trace宏,#define configUSE_TRACE_FACILITY 1。
2.手动实现注册钩子函数
使用背景:
1.实时监视任务的运行周期(统计任务的数量、记录信息)。
2.调试任务资源泄漏(未正确删除任务)。
3.实时分析系统负载。