Embed
DEBUG
在freerots中断言有两种类型。官网描述
- 关中断然后进入死循环,使用调试器定位出错位置
- 进入一个自定义的函数,输出文件名或者文件位置 ``` c /* Define configASSERT() to disable interrupts and sit in a loop. */ #define configASSERT( ( x ) ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
/* Define configASSERT() to call vAssertCalled() if the assertion fails. The assertion has failed if the value of the parameter passed into configASSERT() equals zero. */ #define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( FILE, LINE )
值得注意的是,cubemx自动生成第一种类型的中断,而且是在USER code中生成的。
这意味着只需要将configASSERT定义为空就可以关掉debug设置,而且不会被新生成的代码覆盖。
### 计算任务栈大小
---
#### -fstack-usage
这个参数会生成.su文件,文件中会记录每个函数使用栈大小。[官网描述](https://gcc.gnu.org/onlinedocs/gnat_ugn/Static-Stack-Usage-Analysis.html)
#### -Wstack-usage=128
如果函数栈超过128 bytes,编译器会给出一个警告。
#### uxTaskGetStackHighWaterMark
这个函数会返回未用栈大小(word)。[官网描述](https://www.freertos.org/uxTaskGetStackHighWaterMark.html)
#### vApplicationStackOverflowHook
这个钩子函数在监测到有堆栈溢出时调用。[官网描述](https://www.freertos.org/Stacks-and-stack-overflow-checking.html)
#### 计算任务栈
- 在freertos中绝对不可以使用递归
./avstack.pl *.o cflow *.c
#### 通过debug检查,防止爆栈
``` c
#define INCLUDE_uxTaskGetStackHighWaterMark 1
configASSERT(usTaskGetStackHighWaterMark(xTask) > 32);
通过钩子函数,防止爆栈
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define configCHECK_FOR_STACK_OVERFLOW 2
void vApplicationStackOverflowHook( TaskHandle_t xTask,
signed char *pcTaskName );
总结
经过编译时检查和运行时检查,几乎能消除freertos所有的栈分配不当,提高代码质量。
使用jlink RTT进行调试
jlink官方(UM08001)提供了一种基于内核的调试信息输出。 实现约占ROM 500 bytes,RAM几乎可以忽略。对比串口有如下优点
- 连线少,debug和终端输出都是使用jlink
- 速度快,输出调试信息更多
- RTT库能防止输出冲突
- 实现简单,只需要添加.c文件即可
- 多终端输出支持
添加库
RTT库在 SEEGER/JLINK/Samples/RTT文件夹中。
SEGGER_RTT_Conf.h SEGGER_RTT.h SEGGER_RTT_printf.c SEGGER_RTT.c
将如上文件加入到项目内,编译通过即可使用。调试使用JLinkRTTViewer图形界面。
#include "SEGGER_RTT.c" /× BufferIndex使用0即可,其他buffer需要注册 */ int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); /* 改变接下来的输出终端 */ void SEGGER_RTT_SetTerminal(char TerminalId); /× 不改变输出终端,输出信息 */ int SEGGER_RTT_TerminalOut(char TerminalID, const char *s);
已知bug
- JLinkRTTViewer: 如果输出终端号为0,可以识别\n。其它终端号无法识别\n。解决方案:使用JLinkRTTClent
- 在linux平台对utf8中文字符串识别出错。解决方案:即时调试使用JLinkRTTClient,保存记录使用JLinkRTTViewer