freeRTOS中文实用教程6--错误排查

1.前言

本章主要是为刚接触FreeRTOS 的用户指出那些新手通常容易遇到的问题。这里把最主要的篇幅放在栈溢出以及栈溢出侦测上

2.printf-stdarg.c

当调用标准C 库函数时,栈空间使用量可能会急剧上升,特别是IO 与字符串处理函数,比如sprintf()。在FreeRTOS 下载包中有一个名为printf-stdarg.c 的文件。

这个文件实现了一个栈效率优化版的小型sprintf(),可以用来代替标准C 库函数版本。在大多数情况下,这样做可以使得调用sprintf()及相关函数的任务对栈空间的需求量小很多

3.栈溢出侦测

3.1通过 uxTaskGetStackHighWaterMark()侦测

每个任务都独立维护自己的栈空间,栈空间总量在任务创建时进行设定。
uxTaskGetStackHighWaterMark()主要用来查询指定任务的运行历史中,其栈空间还差多少就要溢出。这个值被称为栈空间的”高水线(High Water Mark)”。

3.2 运行时栈侦测

1.FreeRTOS 包含两种运行时栈侦测机制,由FreeRTOSConfig.h 中的配置常量configCHECK_FOR_STACK_OVERFLOW 进行控制。这两种方式都会增加上下切换开销。

2.栈溢出钩子函数(或称回调函数)由内核在侦测到栈溢出时调用。要使用栈溢出钩子函数,需要进行以下配置:
(1)在FreeRTOSConfig.h 中把configCHECK_FOR_STACK_OVERFLOW 设为1 或2。
(2)提供钩子函数的具体实现,采用如下程序 所示的函数名和函数原型。
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName );

3.栈溢出钩子函数只是为了使跟踪调试栈空间错误更容易,而无法在栈溢出时对其进行恢复。

函数的入口参数传入了任务句柄和任务名,但任务名很可能在溢出时已经遭到破坏

4.栈溢出钩子函数还可以在中断的上下文中进行调用

5.某些微控制器在检测到内存访问错误时会产生错误异常,很可能在内核调用栈溢出钩子函数之前就触发了错误异常中断

3.2.1 运行时栈侦测方法1

1. 当configCHECK_FOR_STACK_OVERFLOW 设置为1 时选用方法1。


2.任务被交换出去的时候,该任务的整个上下文被保存到它自己的栈空间中。这时任务栈的使用应当达到了一个峰值。

3.当configCHECK_FOR_STACK_OVERFLOW 设为1 时,内核会在任务上下文保存后检查栈指针是否还指向有效栈空间。

一旦检测到栈指针的指向已经超出任务栈的有效范围,栈溢出钩子函数就会被调用。

4.方法1 具有较快的执行速度,但栈溢出有可能发生在两次上下文保存之间,这种情况不会被侦测到。

3.2.2 运行时栈侦测方法2

1.将configCHECK_FOR_STACK_OVERFLOW 设为2 就可以选用方法2。方法2在方法1 的基础上进行了一些补充。


2.当创建任务时,任务栈空间中就预置了一个标记。方法2 会检查任务栈的最后20个字节,查看预置在这里的标记数据是否被覆盖。

如果最后20 个字节的标记数据与预设值不同,则栈溢出钩子函数就会被调用。


3.方法2 没有方法1 的执行速度快,但测试仅仅20 个字节相对来说也是很快的。这种方法应该可以侦测到任何时候发生的栈溢出,虽然理论上还是有可能漏掉一些情况,但这些情况几乎是不可能发生的。

 4. 其它常见错误

参见《FreeRTOS中文实用教程》

原文地址:https://www.cnblogs.com/smartjourneys/p/7942174.html