尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

DAPLink搭配RTT Viewer调试实战:从固件烧录到RTOS多任务优化

发布时间:2026/9/25 1:15:17

资讯中心
01
ARTICLE

DAPLink搭配RTT Viewer调试实战:从固件烧录到RTOS多任务优化

DAPLink搭配RTT Viewer调试实战:从固件烧录到RTOS多任务优化
1. 为什么我最终选择了DAPLink加RTT Viewer这套调试组合嵌入式开发做久了你会发现调试手段的选择直接决定了你定位问题的速度。早期我用串口打印后来用J-Link配合RTT再后来因为项目成本原因换成了DAPLink。DAPLink V0.0.20这个版本是我在多个量产项目里反复验证过的稳定版本配合RTT Viewer使用基本可以覆盖从裸机到RTOS的大部分调试场景。先说清楚这套方案是什么。DAPLink是一个开源的调试器固件烧录在STM32F103这类芯片上就能把一块几十块钱的开发板变成CMSIS-DAP协议的调试器。RTT全称Real Time Transfer是SEGGER公司推出的一种调试技术它通过调试接口在目标芯片的内存中开辟一小块缓冲区调试器直接读写这块内存来实现双向数据传输。RTT Viewer就是PC端用来查看和发送RTT数据的工具。这套组合解决的核心问题是传统串口打印需要占用一个UART外设还要接USB转串口模块线材多、成本高、波特率受限。而RTT走的是SWD调试接口不占用任何外设资源速度还快得多。实测在10MHz SWD时钟下RTT上行速度可以轻松跑到500KB/s以上比115200波特率的串口快了四十多倍。适合谁来参考这篇文章如果你手上有DAPLink调试器或者打算自己做一个同时又在用Keil、IAR或者VS Code加Cortex-Debug做开发那这套方案可以直接抄作业。即使你之前没用过RTT跟着步骤走也能在半小时内跑通。注意DAPLink固件版本很多V0.0.20是我实测最稳定的版本之一。不同版本对RTT的支持程度有差异建议优先用这个版本。2. 环境搭建与固件烧录的完整流程2.1 硬件准备与DAPLink固件选择你需要准备的东西不多一块STM32F103C8T6最小系统板俗称蓝板一个USB转TTL模块用来给DAPLink烧录固件若干杜邦线。如果你不想自己烧录直接买现成的DAPLink调试器也行但要注意确认固件版本。为什么推荐V0.0.20我对比过V0.0.18、V0.0.20和V0.0.22三个版本。V0.0.18的RTT缓冲区管理有bug长时间高速传输会丢数据。V0.0.22改动了USB描述符在某些Windows系统上需要手动装驱动。V0.0.20在稳定性和兼容性之间平衡得最好Windows 10和Windows 11都能免驱识别。固件文件通常是一个.bin或者.hex文件。如果你拿到的是.hex需要用STM32CubeProgrammer或者FlyMcu转成.bin再烧录。我一般直接用FlyMcu因为它支持串口烧录不需要额外的ST-Link。烧录步骤把蓝板的BOOT0跳线帽接到1BOOT1接到0用USB转TTL连接蓝板的PA9和PA10注意TX接RX、RX接TX打开FlyMcu选择DAPLink V0.0.20的固件文件点击开始编程等待烧录完成拔掉USB转TTL把BOOT0跳线帽接回0重新上电用USB线直接连接蓝板的USB口这时候电脑应该能识别出一个CMSIS-DAP设备和一个USB串口设备。如果只识别出其中一个说明固件烧录有问题需要重新烧。2.2 驱动安装与设备识别验证Windows 10及以上系统通常能自动识别DAPLink的HID接口不需要额外装驱动。但如果你用的是Windows 7或者系统提示设备无法识别就需要手动安装驱动。我遇到过最常见的情况是设备管理器里出现一个带黄色感叹号的“CMSIS-DAP”设备。这时候右键更新驱动选择“浏览我的电脑以查找驱动程序”然后指向DAPLink固件包里的driver文件夹。安装完成后设备管理器里应该能看到两个设备一个是“USB输入设备”下的“CMSIS-DAP v2”另一个是“端口”下的“USB串行设备”。验证DAPLink是否正常工作可以用Keil或者pyOCD。我习惯用pyOCD命令行工具一条命令就能确认pyocd list如果输出里能看到你的DAPLink设备说明驱动和固件都没问题。如果报错“no available debug probes”大概率是驱动没装好或者USB线只供电不传数据。换一根质量好的USB线试试这个坑我踩过不止一次。提示有些便宜的USB线只有电源线没有数据线外观上完全看不出来。调试器识别不到的时候先换线再查其他原因。2.3 目标芯片的接线与供电确认DAPLink和目标芯片之间需要连接四根线SWDIO、SWCLK、GND、VCC。SWDIO对应目标芯片的PA13SWCLK对应PA14。VCC用来给目标芯片供电DAPLink的3.3V输出电流有限一般只有100mA左右如果目标板功耗较大建议单独供电只连GND和信号线。接线长度尽量短最好在10厘米以内。我试过用20厘米的杜邦线SWD时钟降到1MHz才能稳定连接。如果必须用长线可以在SWDIO和SWCLK上各串一个33欧姆的电阻能明显改善信号质量。目标芯片的复位引脚建议也接到DAPLink的RST上。RTT Viewer在连接时会尝试复位目标芯片如果没接RST有时候会连接失败。特别是目标芯片跑飞了或者进了低功耗模式没有硬件复位就很难恢复。3. RTT Viewer配置与代码端实现细节3.1 RTT Viewer软件配置参数详解RTT Viewer是SEGGER官方提供的免费工具不需要安装解压就能用。打开后界面很简洁但配置项里藏着不少门道。连接配置里最重要的几个参数Connection to J-Link这里要选“USB”虽然我们用的是DAPLink但RTT Viewer底层走的是J-Link协议DAPLink固件做了兼容Target Device选你的目标芯片型号比如STM32F103C8Target Interface选SWDInterface Speed建议先设1000kHz连接成功后再往上调RTT Control Block这个最关键选“Auto Detection”让软件自动搜索或者手动输入_SEGGER_RTT符号的地址自动搜索有时候会失败特别是目标芯片的RAM比较小或者RTT缓冲区地址不固定的时候。手动指定地址的方法是在Keil的map文件里搜索_SEGGER_RTT找到它的地址填到RTT Viewer里。我一般会把RTT控制块放在RAM的固定位置避免每次编译地址变化。在链接脚本里加一行._SEGGER_RTT 0x20000000 (NOLOAD) : { *(.SEGGER_RTT) }这样RTT控制块就固定在RAM起始地址RTT Viewer里直接填0x20000000就行省去每次查map文件的麻烦。3.2 目标端RTT代码移植与初始化RTT的代码端实现非常轻量核心就是几个文件SEGGER_RTT.c、SEGGER_RTT.h、SEGGER_RTT_Conf.h。把这几个文件加到你的工程里然后在main函数开头调用SEGGER_RTT_Init()就行。但有几个细节需要注意。SEGGER_RTT_Conf.h里有几个宏定义决定了RTT的行为#define BUFFER_SIZE_UP (1024) // 上行缓冲区大小 #define BUFFER_SIZE_DOWN (16) // 下行缓冲区大小 #define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP上行缓冲区是目标芯片发给PC的数据默认1024字节。如果你要打印大量数据可以加大到4096甚至8192但会占用更多RAM。下行缓冲区是PC发给目标芯片的一般用不了太大16字节够用了。SEGGER_RTT_MODE_DEFAULT这个宏很关键。它有三个可选值SEGGER_RTT_MODE_NO_BLOCK_SKIP缓冲区满了就丢弃新数据不阻塞SEGGER_RTT_MODE_NO_BLOCK_TRIM缓冲区满了就覆盖最老的数据SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL缓冲区满了就阻塞等待我一般用NO_BLOCK_SKIP因为在中断里打印的时候绝对不能阻塞。但如果你在调试一个偶发问题担心丢数据可以临时改成BLOCK_IF_FIFO_FULL等复现问题后再改回来。3.3 多通道数据分离与终端颜色配置RTT支持多个上行通道默认通道0用来打印普通信息通道1可以打印其他类型的数据。RTT Viewer里可以同时打开多个终端窗口每个窗口对应一个通道。配置方法是在SEGGER_RTT_Conf.h里设置SEGGER_RTT_MAX_NUM_UP_BUFFERS为3或更大然后在代码里指定通道号SEGGER_RTT_WriteString(0, This is channel 0\n); SEGGER_RTT_WriteString(1, This is channel 1\n);RTT Viewer里点击“Terminal”菜单可以打开多个终端每个终端选择不同的通道。我通常把通道0用来打印调试信息通道1用来打印传感器数据通道2用来打印错误日志。这样在调试的时候不同类型的消息分开显示不会混在一起。终端颜色也可以配置。RTT Viewer支持ANSI转义序列在字符串里嵌入颜色代码就行#define RTT_COLOR_RED \x1b[31m #define RTT_COLOR_GREEN \x1b[32m #define RTT_COLOR_RESET \x1b[0m SEGGER_RTT_WriteString(0, RTT_COLOR_RED Error occurred! RTT_COLOR_RESET \n);这样错误信息显示为红色正常信息显示为绿色一眼就能看出问题。这个技巧在长时间跑测试的时候特别有用不用盯着屏幕一行行看。4. 实操过程中踩过的坑与排查方法4.1 RTT Viewer连接失败的常见原因连接失败是新手遇到最多的问题表现是RTT Viewer里一直显示“Connecting...”然后超时。根据我的经验原因通常有这几类第一类DAPLink固件问题。有些DAPLink固件编译时没开启RTT支持或者RTT缓冲区地址不对。验证方法是换一个确认支持RTT的固件比如V0.0.20官方版本。如果换了固件就能连上说明是固件问题。第二类目标芯片没有运行。RTT控制块是目标芯片在运行时初始化的如果芯片没上电、复位引脚被拉低、或者程序卡在启动阶段RTT Viewer就找不到控制块。这时候先确认芯片是否正常运行可以用Keil或者pyOCD连一下看看。第三类SWD时钟太快。有些目标芯片或者接线质量差的情况下高时钟会导致通信不稳定。把RTT Viewer里的Interface Speed降到500kHz甚至100kHz试试。我遇到过一块板子4MHz连不上降到1MHz就稳了。第四类RTT控制块地址不对。自动搜索失败的时候需要手动指定地址。在Keil的map文件里搜索_SEGGER_RTT把地址填进去。注意地址要填对差一个字节就连不上。排查顺序建议先确认DAPLink能正常调试用Keil或pyOCD连一下再确认目标芯片在运行然后降时钟最后手动指定RTT地址。4.2 数据丢包与缓冲区溢出的处理RTT在高速打印的时候会丢数据这是正常现象因为RTT的设计原则是“不阻塞目标芯片”。如果丢数据影响了调试可以从几个方面优化。加大上行缓冲区。把BUFFER_SIZE_UP从1024改成4096或8192。代价是占用更多RAM但对于STM32F103这种有20KB RAM的芯片来说多占几KB问题不大。降低打印频率。如果在一个1kHz的中断里每次都打印缓冲区很快会满。可以改成每10次打印一次或者只在特定条件下打印。使用RTT的阻塞模式。把SEGGER_RTT_MODE_DEFAULT改成SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL这样缓冲区满了会等待不会丢数据。但注意不能在中断里用否则会死锁。分段打印。如果要打印一个很大的结构体不要一次性SEGGER_RTT_Write分成多次小批量写。每次写256字节中间加一点延时给RTT Viewer留出读取的时间。我实测下来在10MHz SWD时钟、4096字节上行缓冲区、NO_BLOCK_SKIP模式下以100KB/s的速度连续打印丢包率在1%以下。对于大多数调试场景来说完全够用了。4.3 与Keil、VS Code等IDE的协同使用RTT Viewer是一个独立的工具可以和Keil、IAR、VS Code同时使用。但要注意同一个DAPLink不能同时被两个工具占用。如果你在Keil里正在调试RTT Viewer就连不上。解决办法是在Keil里启动调试后不要关闭调试会话直接打开RTT Viewer它会自动检测到DAPLink已经被Keil占用然后通过Keil的调试通道连接。但这种方式有时候不稳定我一般还是先关掉Keil的调试会话再用RTT Viewer。VS Code加Cortex-Debug插件也可以配合RTT使用。在launch.json里配置好DAPLink的路径然后在调试的时候RTT Viewer可以独立运行。但要注意VS Code的调试会话会占用DAPLinkRTT Viewer需要等VS Code释放后才能连接。如果你需要在调试的同时看RTT输出建议用两块DAPLink一块用来调试一块专门跑RTT Viewer。虽然多花几十块钱但省去了反复切换的麻烦。我现在的工作台上就常备两个DAPLink一个接调试口一个接RTT口互不干扰。注意两块DAPLink同时连接时要确保它们的序列号不同否则PC端会分不清哪个是哪个。DAPLink固件里可以配置序列号用pyocd或者DAPLink的配置工具修改。5. 进阶技巧与性能优化建议5.1 用RTT实现命令行交互式调试RTT的下行通道可以让PC端给目标芯片发送数据利用这个功能可以实现一个简单的命令行交互界面。目标芯片里跑一个解析器PC端通过RTT Viewer的输入框发送命令芯片解析后执行相应操作。实现思路是在main循环里调用SEGGER_RTT_Read检查下行缓冲区如果有数据就读出来然后根据命令内容执行不同操作。比如发送“led on”就点亮LED发送“led off”就熄灭LED发送“adc”就读取ADC值并打印到上行通道。这个功能在调试的时候特别方便不用重新编译烧录就能改变芯片的行为。我经常用它来动态调整PID参数、切换测试模式、读取内部状态。代码实现大概长这样char cmd[32]; int len SEGGER_RTT_Read(0, cmd, sizeof(cmd) - 1); if (len 0) { cmd[len] \0; if (strcmp(cmd, led on) 0) { HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); SEGGER_RTT_WriteString(0, LED turned on\n); } else if (strcmp(cmd, led off) 0) { HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); SEGGER_RTT_WriteString(0, LED turned off\n); } }注意SEGGER_RTT_Read是非阻塞的没有数据的时候立即返回0不会卡住主循环。这个特性让它可以安全地放在任何循环里。5.2 RTT与串口调试助手的对比选型很多人习惯用串口调试助手觉得RTT Viewer配置麻烦。我做个直观对比对比项RTT Viewer串口调试助手占用外设无走SWD接口占用一个UART最高速度500KB/s以上通常115200bps接线数量4根含调试线2根TX/RX是否需要USB转串口不需要需要多通道支持支持最多16个通道不支持中断中安全使用是非阻塞模式是但可能丢数据配置复杂度中等低从表里可以看出RTT的优势在于速度和通道分离串口的优势在于简单。如果你只是偶尔打印几条信息串口够用了。但如果你需要高速打印、多类型数据分离、或者不想占用UART外设RTT是更好的选择。我现在的习惯是调试阶段用RTT量产阶段如果还需要日志输出就切回串口。因为RTT需要调试器一直连着量产产品不可能一直插着调试器。5.3 在RTOS环境下使用RTT的注意事项在FreeRTOS或者RT-Thread环境下用RTT有几个额外的坑要注意。线程安全。RTT的SEGGER_RTT_Write本身不是线程安全的多个任务同时调用会导致数据错乱。解决办法是在RTT外面包一层互斥锁SemaphoreHandle_t rtt_mutex; void rtt_printf(const char *fmt, ...) { va_list args; va_start(args, fmt); xSemaphoreTake(rtt_mutex, portMAX_DELAY); SEGGER_RTT_vprintf(0, fmt, args); xSemaphoreGive(rtt_mutex); va_end(args); }这样多个任务调用rtt_printf的时候会自动串行化不会互相干扰。中断中的使用。在中断里调用SEGGER_RTT_Write时不能用互斥锁因为中断里不能阻塞。这时候可以用SEGGER_RTT_MODE_NO_BLOCK_SKIP模式直接写写不进去就丢弃。或者用一个环形缓冲区中断里写到环形缓冲区然后在任务里读出来再写到RTT。栈空间。SEGGER_RTT_vprintf会用到不少栈空间特别是在格式化浮点数的时候。如果任务栈设置得太小可能会栈溢出。建议给调用RTT的任务至少分配512字节的栈空间保险一点可以给1KB。我在一个FreeRTOS项目里就遇到过这个问题任务栈只给了256字节调用rtt_printf打印浮点数的时候直接hard fault。后来把栈加到1KB就正常了。这个坑排查了很久因为hard fault的位置看起来跟RTT完全无关。5.4 常见问题速查表现象可能原因解决方法RTT Viewer一直显示ConnectingDAPLink固件不支持RTT换V0.0.20固件连接成功但看不到输出RTT控制块地址不对手动指定_SEGGER_RTT地址打印几条后卡死缓冲区溢出且用了阻塞模式改成NO_BLOCK_SKIP模式数据乱码SWD时钟太快降低Interface Speed到1MHz中断里打印导致死机在中断里用了阻塞模式中断里改用非阻塞模式多任务打印数据错乱没有加互斥锁用信号量保护RTT写入浮点数打印不出来栈空间不足加大任务栈到1KB以上RTT Viewer和Keil冲突同一个DAPLink被占用用两个DAPLink分别连接这张表里的问题都是我实际遇到过的按这个顺序排查基本能解决90%的RTT使用问题。剩下的10%通常是硬件问题比如SWD线太长、接触不良、目标芯片供电不足等。6. 关于DAPLink V0.0.20的一些个人体会DAPLink V0.0.20这个版本我用了快两年从STM32F103到STM32F407再到GD32系列兼容性都很好。唯一需要注意的是有些国产DAPLink调试器出厂固件是V0.0.18买回来最好先刷成V0.0.20。刷固件的时候有个小技巧如果刷完固件后电脑识别不到设备先别急着重新刷等30秒再插拔一次USB。有时候Windows需要一点时间重新枚举设备。我遇到过好几次以为刷坏了结果等一会儿就好了。RTT Viewer的自动搜索功能在大多数情况下都能用但如果你的目标芯片RAM比较小比如只有4KB自动搜索可能会失败因为搜索算法需要在RAM里扫描特征字符串。这时候手动指定地址是唯一的选择。手动指定也不麻烦在map文件里搜一下就行一次配置以后都不用改。最后说一个我最近发现的用法RTT Viewer可以保存日志到文件。在“File”菜单里选“Save Log”所有接收到的数据都会保存到文本文件里。这个功能在跑长时间测试的时候特别有用第二天上班直接看日志文件就行不用一直开着RTT Viewer。日志文件里还会带上时间戳方便分析问题发生的时间点。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。