DEBUG#
在freerots中断言有两种类型。官网描述
- 关中断然后进入死循环,使用调试器定位出错位置
- 进入一个自定义的函数,输出文件名或者文件位置
1
2
3
4
5
6
| /* 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文件,文件中会记录每个函数使用栈大小。官网描述
-Wstack-usage=128#
如果函数栈超过128 bytes,编译器会给出一个警告。
uxTaskGetStackHighWaterMark#
这个函数会返回未用栈大小(word)。官网描述
vApplicationStackOverflowHook#
这个钩子函数在监测到有堆栈溢出时调用。官网描述
计算任务栈#
1
2
| ./avstack.pl *.o
cflow *.c
|
通过debug检查,防止爆栈#
1
2
| #define INCLUDE_uxTaskGetStackHighWaterMark 1
configASSERT(usTaskGetStackHighWaterMark(xTask) > 32);
|
通过钩子函数,防止爆栈#
1
2
3
4
| #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文件夹中。
1
2
3
4
| SEGGER_RTT_Conf.h
SEGGER_RTT.h
SEGGER_RTT_printf.c
SEGGER_RTT.c
|
将如上文件加入到项目内,编译通过即可使用。调试使用JLinkRTTViewer图形界面。
1
2
3
4
5
6
7
| #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