嵌入式 printf的几种办法 (ITM、SWO、semihosting、Keil Debug Viewer、RTT、串口重定向printf)

关键词:

ITM、SWO、semihosting、Keil Debug Viewer、RTT、串口重定向printf。

名词释义

ITM: https://blog.csdn.net/hanchaoman/article/details.

SWO: https://blog.csdn.net/weixin_30407613/article/details.

semihosting:半主机模式 https://blog.csdn.net/yhneng/article/details/6299893.
需要注意的是,我并没有学会半主机模式,该方式似乎是对调试器有特殊要求,JLINK不能实现,并且ARM后面又推出了ITM机制,所以下文不再讲述半主机的printf方式

Keil Debug Viewer : https://blog.csdn.net/yhneng/article/details/6299893.

参考博客(大牛)

https://blog.csdn.net/ybhuangfugui/article/details/94378013

打印的几种方式printf

1.软件仿真打印输出

2.串口UART打印输出

3.SWO打印输出

4.JLink-RTT打印输出

printf方式优点缺点
软件仿真printf无须硬件很多项目不能运行
串口打印适用于正式运行产品、无须调试器串口打印耗时,影响MCU的实时性
SWO打印不影响MCU的实时性必须使用仿真器
RTT打印不影响MCU的实时性必须使用JLINK

来看一下实时性的对比图:
打印82个字符
RTT仅耗时1us
SWO耗时120us(速率设置为1500Khz)
半主机模式耗时10.7ms
串口打印耗时约1ms(波特率115200情况下)

在实时性上,RTT > SWO >串口 >半主机模式
在这里插入图片描述

1软件仿真printf

何为软件仿真printf? 就是只在集成开发环境中模拟printf仿真输出,不需要连接开发板(硬件MCU)即可实现。
这种方法非常不推荐,因为软件仿真与真实环境有很大的差异,很多工程代码,在软件仿真的时候根本跑不了。就会出现卡在某个地方不动的尴尬情况(软件仿真的时候会有绿色的方框,如下图)
在这里插入图片描述

如果你不清楚,可以参照,以下所有的博客都是指的软件仿真:
软件仿真https://blog.csdn.net/ybhuangfugui/article/details/94378195?

半主机模式的软件仿真https://blog.csdn.net/zhc335134701/article/details/81261070?

keil软件仿真https://blog.csdn.net/weixin_45380951/article/details/103372085?.

没错,基本上博客写明Use Simulator ,并修改Dialog DLL的情况都是软件仿真。
在这里插入图片描述

2串口重定向printf

这种方式有非常多的博客可以参考,例如:
串口重定向博客1https://blog.csdn.net/qq_39101111/article/details
串口重定向博客2https://blog.csdn.net/zouleideboke/article/details

串口重定向博客3https://blog.csdn.net/qq_22329595/article/details

该方式比较简单,不再重复论述。

3SWO打印输出printf

3.1名词释义

先看此博客使用SWO代替UART,实现Printf打印功能https://blog.csdn.net/qq_37663138/article/details

再稍微解释一下:
1 在Cortex-M3\M4\M7系列MCU中,内核的调试组件有一个仪器跟踪宏单元(ITM) 。请注意如果你的芯片是 Cortex-M0 或者其他ARM内核,不支持ITM
什么是ITM请看这里https://blog.csdn.net/leekay123/article/details

3.2硬件接线

我们都知道SWD接口正常使用是四根线。而使用ITM需要多使用到SWD一根线:SWO.
先找一找JLINK接口定义SWO的位置:
在这里插入图片描述再找出你的原理图上,SWO的管脚位置:(我的项目此处使用stm32f407ze)
在这里插入图片描述查清楚以后,用杜邦线连接板子上PB3 和JLINK的13脚。

3.3软件配置

3.3.1SWO管脚配置

注意需要配置PB3为SWO. 如果是使用stm32cube mx, 可以直接按下图使能即可。
如果是其他芯片或者自己使用标准库,则需要编写代码,确保管脚配置正确。
在这里插入图片描述

3.3.2重定向代码添加

可以新建一个.c文件,也可以放在任何一个现有.c文件中。

#include "stdio.h"
#define ITM_Port8(n)    (*((volatile unsigned char *)(0xE0000000+4*n)))
#define ITM_Port16(n)   (*((volatile unsigned short*)(0xE0000000+4*n)))
#define ITM_Port32(n)   (*((volatile unsigned long *)(0xE0000000+4*n)))

#define DEMCR           (*((volatile unsigned long *)(0xE000EDFC)))
#define TRCENA          0x01000000

struct __FILE { int handle; /* Add whatever needed */ };
FILE __stdout;
FILE __stdin;

int fputc(int ch, FILE *f) {
  if (DEMCR & TRCENA) {
    while (ITM_Port32(0) == 0);
    ITM_Port8(0) = ch;
  }
  return(ch);
}
3.3.3使用keil查看、设置

1 使用微库
在这里插入图片描述2 使能debug setting- trace

在这里插入图片描述

3.3.3使用JLINK-SWO Viewer查看、设置

下面是使用J-Link SWO Viewer 查看的,这种方式可以不进入debug模式。每次产品上电后都需要退出软件,并重新选择器件和频率。
在这里插入图片描述

3.4查看效果

需要说明以下几点:
Core Clock一定要保持与主频,也就是系统时钟频率一致。如果不一致后面没有任何输出。
在这里插入图片描述

默认ITM是端口0,一共可以使用32个端口,如果想使用其他端口,需要修改重定向代码内容,例如使用端口8

int fputc(int ch, FILE *f) {
  if (DEMCR & TRCENA) {
    while (ITM_Port32(8) == 0);
    ITM_Port8(8) = ch;
  }

我这里是移植了LWIP代码,需要打开LWIP的打印使能。
下面是用keil Debug Viewer里面查看的,由于keil软件的限制,必须要进入debug 模式,才能打开Debug Viewer窗口
在这里插入图片描述

查看效果
在这里插入图片描述

3.5 SWO的其他功能

用SWO测量代码运行时间https://blog.csdn.net/weixin_34004576/article/details

4Link-RTT打印输出

这个功能只是进行了初步使用,没有非常详细使用,打算放到后面专门讲RTT。
如果只是想使用RTT打印功能,可以参考如下内容
https://blog.csdn.net/gyb510/article/details

https://blog.csdn.net/ybhuangfugui/article/details

5总结

本文讲述了打印Printf的四种方式,并着重讲述了如何用SWO的方式将信息打印出来.四种方式没有完全绝对的优劣,可以根据实际情况进行选择。
希望本文对读者有帮助,记得点个赞哦。

### RTThread 开发在 MDK (Keil Microcontroller Development Kit) 环境下的配置指南 #### 配置环境准备 为了使 RTThread 能够正常工作于 MDK 工具链环境中,需完成一系列必要的设置。这些设置包括但不限于工具链版本的选择、工程模板的创建以及特定功能模块的支持。 - 使用最新版的 Keil MDK 是推荐的做法,因为新版本通常会提供更好的兼容性和性能优化[^1]。 - 创建一个新的 STM32 工程或者基于现有的裸机项目进行改造。确保目标芯片型号已正确选择并加载相应的启动代码和外设驱动程序。 #### 半主机支持与调试接口 RTThread 支持多种调试方式,在嵌入式开发中常用的有 **Semihosting** 和 **ITM/SWO** 输出两种主要手段: - Semihosting 提供了一种简单的方法用于从目标设备向宿主机发送数据流(如标准输出)。然而它依赖 JTAG 或 SWD 接口连接,并可能带来额外开销。 如果计划采用此技术,则需要确认以下几点: - 启用了 `-u _printf_float` 编译器选项以允许浮点数打印; - 在链接阶段加入 `--specs=rdimon.specs` 参数启用 runtime I/O monitor 功能; - 对于更高效的解决方案可以考虑 ITM/SWO 方法。这种方法通过串行线观察(Serial Wire Output)通道传输少量字符信息而不影响实时表现[^3]。要激活该特性,请按照如下步骤操作: - 定义宏定义 `USE_ITM_printf`; - 修改默认的标准 IO 实现路径至 CMSIS 提供的相关 API 如 `ITM_SendChar()` 等[^2]; ```c #include "core_cmFunc.h" int fputc(int ch, FILE *f){ ITM_SendChar(ch); return ch; } ``` #### Map 文件分析 当遇到复杂的符号解析问题时,生成详细的 map 文件有助于理解整个系统的内存布局情况及其内部调用关系网状结构。这一步骤对于排查潜在冲突特别有用。 要在构建过程中获取此类文档,只需调整 linker script 中的相关参数即可: ```bash --verbose --list rtt.map ``` 上述指令将会把最终的结果保存到当前目录下一个叫做 'rtt.map' 的纯文本文件里。 #### 整合 RTConsole 设备模型 Grissiom 曾经提议过一种创新性的思路——即将半主机视为独立硬件抽象层中的一个特殊装置实例对待。这样做的好处是可以无缝集成进 FinSH 命令解释框架当中去从而简化交互逻辑设计过程: ```c rt_console_set_device("semi"); ``` 以上代码片段展示了如何快速切换终端显示媒介为先前提到过的那个虚拟实体对象。“semi”代表的就是这里所指代的那个概念化后的组件名称。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值