[应用相关] ITM_SendChar函数的使用

[复制链接]
175|0
八层楼 发表于 2025-8-12 17:05 | 显示全部楼层 |阅读模式
ITM_SendChar 是 ARM Cortex-M 微控制器中用于通过 ​​ITM(Instrumentation Trace Macrocell)机制​​输出调试信息的关键函数,它通过 SWO(Serial Wire Output)引脚实现高速、低干扰的调试信息传输,尤其适合替代传统串口输出。以下是详细使用指南:


​​一、ITM_SendChar 的原理与优势​​
​​工作原理​​

ITM 是 Cortex-M3/M4/M7 内核内置的调试模块,支持 32 个刺激端口(Stimulus Ports)。
ITM_SendChar 将字符写入 ITM 的端口 0(默认端口),通过 SWO 引脚输出到调试器(如 J-Link、ST-Link)。
​​无需暂停程序​​:数据在程序全速运行时异步传输,不影响实时性。
​​核心优势​​

​​高速传输​​:波特率可达数 Mbps(取决于内核时钟)。
​​零硬件占用​​:仅需 1 根 SWO 引脚(通常为 PB3),不占用串口资源。
​​支持标准库函数​​:可重定向 printf 直接输出调试信息。

​​二、硬件连接要求​​
​​引脚连接​​

​​目标板​​:连接 MCU 的 ​​SWO 引脚(PB3)​​ 到调试器的 ​​SWO 接口​​(调试器 20 针接口的第 9 脚)。
​​调试器​​:使用支持 SWO 的调试器(如 ST-Link V2/V3、J-Link)。
​​接线示例​​:
MCU PB3 → 调试器 SWO 引脚
MCU SWDIO → 调试器 SWDIO
MCU SWCLK → 调试器 SWCLK
GND → GND


​​注意事项​​

​​Cortex-M0/M0+ 不支持​​:仅 M3/M4/M7 内核可用。
​​时钟匹配​​:调试器配置的 CPU 时钟必须与实际频率一致(否则无输出)。

​​三、软件配置步骤​​
1. ​​工程设置(以 Keil MDK 为例)​​
​​启用 Trace​​:
Options for Target → Debug → Settings → Trace
勾选 ​​Enable Trace​​,设置 ​​Core Clock​​(如 168 MHz),选择 ​​ITM Stimulus Port 0​​(默认端口)。
​​SWO 参数​​:
Trace Port: Serial Wire Output,Prescaler 根据时钟计算(如 168 MHz 时设为 2)。
2. ​​代码重定向​​
重写 fputc 函数,调用 ITM_SendChar:
#include <stdio.h>
#include "core_cm4.h"  // 根据内核选择 core_cm3.h 或 cm4.h

// 重定向 printf
int fputc(int ch, FILE *f) {
    return ITM_SendChar(ch);  // 发送字符到 ITM 端口 0
}


​​多端口支持​​:
若需使用其他端口(如端口 1),修改为:
#define ITM_PORT1 0x00000001
ITM->PORT[1].u8 = ch;  // 发送到端口 1


3. ​​测试代码​​
int main(void) {
    while (1) {
        printf("ADC Value: %d\n", read_adc());  // 直接使用 printf
        delay_ms(100);
    }
}

​​四、调试信息查看​​

​​Keil MDK​​

进入调试模式:Debug → Start/Stop Debug Session。
打开输出窗口:View → Serial Windows → Debug (printf) Viewer。
​​其他工具​​

​​ST-Link Utility​​:SWV → Serial Wire Viewer。
​​J-Link SWO Viewer​​:独立工具,支持波形显示。

​​五、常见问题解决​​
​​无输出信息​​

​​时钟不匹配​​:检查调试器中设置的 Core Clock 是否与实际一致。
​​SWO 引脚未启用​​:在 MCU 初始化代码中启用 PB3 的复用功能(部分需配置 GPIO)。
​​端口未使能​​:在 Keil Trace 配置中勾选 ​​ITM Stimulus Port 0​​。
​​输出乱码​​

​​波特率错误​​:调整 Prescaler 值(公式:SWO 频率 = Core Clock / (Prescaler + 1))。
​​中断冲突​​:避免在中断服务函数中频繁调用 printf(改用缓冲队列)。

​​六、高级用法​​
​​多端口分类输出​​

void debug_log(uint8_t port, char *msg) {
    while (*msg) {
        ITM->PORT[port].u8 = *msg++;  // 指定端口发送
    }
}


​​应用场景​​:端口 0 输出日志,端口 1 输出错误信息,便于过滤。
​​2.与 RTT 对比​​




​​七、最佳实践建议​​
​​替代串口调试​​:在资源受限或高速场景下优先使用 ITM,节省硬件串口。
​​时钟校准​​:在 SystemInit() 后读取 SystemCoreClock 动态设置 Trace 时钟。
​​生产环境禁用​​:通过宏定义控制调试输出,避免性能损耗:
#ifdef DEBUG_ENABLE
  #define LOG printf
#else
  #define LOG(...)
#endif


————————————————
版权声明:本文为CSDN博主「风停了123」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/2301_79036162/article/details/148892846

您需要登录后才可以回帖 登录 | 注册

本版积分规则

131

主题

4396

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部