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官方(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