Debug过程中,使用printf()函数能给输出数据带来很大方便,这归功于printf对各种数据类型转换的强大能力。MCU系统中使用printf的核心技巧是定制一个自己的fputc函数,关于这方面介绍的内容网上有很多,不熟悉的读者请自行百度。下面介绍ITM如何与printf结合来输出debug信息。先以KEIL为例。KEIL软件考虑的很周到,官方给了一个重定向printf的代码例子:
在KEIL安装目录下的 ARM\Startup\ 目录下,有一个名叫 Retarget.c 的文件,里面定义了FILE数据类型和一些输入、输出的底层函数,我们只保留FILE声明和fputc输出函数,其余删掉,改造后的 retarget.c 文件如下:
#include
#include "stm32f4xx_hal.h"
#pragma import(__use_no_semihosting_swi)
//extern int sendchar(int ch); /* in Serial.c */
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f) {
//return (sendchar(ch));
return (ITM_SendChar(ch));
}
因为本人的目标板是NUCLEO-F411RE 板子,所以include了头文件 stm32f4xx_hal.h ,是为了调用 ITM_SendChar() 函数。这样修改代码之后,主程序调用printf,printf调用fputc,fputc调用ITM_SendChar(),最终在KEIL的ITM观察窗口中输出我们要看的变量的数值。(有关如何在KEIL中使用ITM功能,请见STM32的ITM跟踪调试功能在KEIL中的应用)
将这个retarget.c文件加入到KEIL工程项目中,在main.c中添加一个打印输出语句:
printf("Hello, st mcu!\n");
编译、烧写程序,启动debug调试、全速运行,看到结果如下:
再看一个打印变量值的小例子,man.c中增加一个变量:
uint32_t dwCount;
然后,printf语句修改为:
printf("cnt = [%4d]\n", dwCount++); //右对齐,占4个字符位宽
运行结果如下:
可见,使用printf可以非常灵活地控制输出数据的格式。
小结:
改造fputc函数来“重定向”打印输出;
增加一个retarget.c文件,include 2个头文件:stdio.c 和 stm32f4xx_hal.h(你可以修改成你的目标板MCU对应的HAL头文件),改写fputc函数;
在main.c或其他需要打印输出的地方,直接使用printf()即可。
本文完,请见ITM专题系列的最后一篇:ITM应用实例:USB设备(模拟一个鼠标)代码调试。