本帖最后由 zhanzr21 于 2017-12-31 17:36 编辑
补: ITM重定向IO
这个内容我发过一两次了, 但是还是有很多工程师对这个不熟, 本着共享知识的精神, 不怕别人说啰嗦再发一次.
所谓重定向IO,就是将此标准输出输入接口重定向到能看到的界面, 以便调试观察.
比如:
printf("Coremark For STM32L4R5 Nucleo Board [url=home.php?mod=space&uid=72445]@[/url] %u Hz, %u, %u, %u\n",
SystemCoreClock, HAL_RCC_GetHCLKFreq(), HAL_RCC_GetSysClockFreq(), HZ);
这种代码, 如果在Host机器上编译运行, 现象是Console界面看到打印.
如果是嵌入式平台, Console是没有的, 一般情况下可以将其重定向到串口上, 但是如果该CPU与调试器有ITM接口, 将其重定向到ITM接口上将更加方便.
ST所有的Cortex M3及以上的内核都支持ITM输出
所有的Nucleo板子上的调试器都支持捕捉ITM输出
Cortex M0/M0+的处理器一般没有此接口, 为的是节省资源.
如果要输出ITM, SWD接口除了SWCLK, SWDIO之外, 还要接一根SWO,也称SWV的IO.
在Cube中这么设置:
至于JTAG口, 另有设置, 这里暂时不节外生枝
在生成的代码中需要提供相关的输出函数.
在RTE配置界面这样配置:
如果是重定向到串口, 相应的OUT配置成User, 这里选ITM.
因为RTE自己本身就有ITM的输出函数(属于内核), 所以这样之后, 就可以使用printf了:
static int stdout_putchar (int ch) {
return (ITM_SendChar(ch));
}
如果是重定向到串口, 则需要重新实现这个stdout_putchar函数,直接输出到串口上即可.
如果不是Keil MDK开发, 使用GCC来开发, 则不需设置RTE, 只需要重新实现这个函数即可:
//Retarget IO to ITM
int _write(int file, char *data, int len)
{
for(int i=0; i<len; ++i)
{
ITM_SendChar(*(data+i));
}
return len;
}
如果要使用scanf函数,则还要实现_read函数, 只是调试的话一般printf最为常用.
如果是ST-LINK调试器, 输出使用ST-LINK Utility工具查看即可:
注意,时钟要跟内核时钟配置成一样子.
补充完毕.
|