一、任务创建堆栈分配原理
如果 使用 xTaskCreate() 创建任务, 则用作任务堆栈的内存会从 FreeRTOS 堆中自动分配, 并通过传递至 xTaskCreate() API 函数的参数来确定内存大小。
如果 使用 xTaskCreateStatic() 创建任务,则用作任务堆栈的内存由 应用程序编写者预先分配。
FreeRTOS 提供两个可选机制,用于协助检测并纠正 出现的堆栈溢出问题。使用的选项通过 configCHECK_FOR_STACK_OVERFLOW 配置常量来配置。
Ps: 这些选项仅适用于内存映射未分段的架构。 此外,在 RTOS 内核溢出检查开始之前,某些处理器可能会因堆栈损坏而 发生故障或异常。
二、堆栈溢出检测
1. stm32cubeide 配置

2.函数原型
堆栈溢出检查会增加上下文切换的开销,因此建议只在开发或测试阶段使用 此检查。
// 函数原型
void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
xTask 和 pcTaskName 参数分别将违规任务的句柄和名称传递给该钩子函数。 但请注意,根据溢出的严重程度,这些参数本身可能会损坏,在这种情况下, 可直接检查 pxCurrentTCB 变量。
3.栈溢出检测方法
1.堆栈溢出检测——方法 1
在 RTOS 内核使任务退出运行状态后,堆栈可能达到其最大(最深)值, 因为此时的堆栈会包含任务上下文。此时, RTOS 内核可以检查处理器堆栈指针是否仍处于有效堆栈空间内。如果堆栈指针 包含超出有效堆栈范围的值,则将调用堆栈溢出钩子函数。
特点:此方法很快,但不能保证可以捕获所有堆栈溢出。将 configCHECK_FOR_STACK_OVERFLOW 设置 为 1 即可使用此方法。
2.堆栈溢出检测——方法 2
任务首次创建时,其堆栈会填充一个已知值。任务退出运行状态时, RTOS 内核可以检查最后 16 个字节是否处于有效堆栈范围内,以确保这些已知值 未被任务或中断活动所覆盖。如果这 16 个字节中的任何一个不再为初始值, 则调用堆栈溢出钩子函数。
特点:这种方法比方法 1 效率低,但仍然相当快。它很可能会捕获堆栈溢出, 但仍无法保证能够捕获所有溢出。
将 configCHECK_FOR_STACK_OVERFLOW 设置为 2 即可使用此方法。
3.堆栈溢出检测——方法 3
此方法仅适用于选定的端口。如果可用,该方法将启用 ISR 堆栈检查。 检测到 ISR 堆栈溢出时,会触发断言。请注意,在这种情况下不会调用堆栈溢出钩子函数, 因为它只针对任务堆栈,而不是针对 ISR 堆栈。
将 configCHECK_FOR_STACK_OVERFLOW 设置为 3 即可使用此方法。
三、任务运行状态查询
1. stm32cubeide 配置

2.代码实现
void MonitorTask(void *argument)
{
/* USER CODE BEGIN MonitorTask */
static uint8_t mytaskstatebuffer[512];
/* Infinite loop */
for(;;)
{
memset(mytaskstatebuffer, 0, sizeof(mytaskstatebuffer));
strcpy((char *)mytaskstatebuffer,
"==================================\r\n"
"任务名 任务状态 优先级 剩余栈 任务序号\r\n");
// 假设 osThreadList 是追加写入的
vTaskList(mytaskstatebuffer + strlen((char *)mytaskstatebuffer));
size_t len = strlen((char *)mytaskstatebuffer);
HAL_UART_Transmit_DMA(&huart6, mytaskstatebuffer, len);
osDelay(3000);
}
/* USER CODE END MonitorTask */
}

9

被折叠的 条评论
为什么被折叠?



