资讯动态

基于STM32F103RCT6移植DAPLink并在Keil5中集成RTT Viewer打印

发布时间:2026/8/31 8:18:14 来源:尧图企业网站定制
简介本资源是一份面向嵌入式开发工程师与进阶单片机学习者的STM32F103RCT6硬件平台实战工程聚焦于DAPLINK固件移植与实时调试能力构建解决传统串口打印效率低、调试信息滞后等痛点。压缩包含819个文件主体为473个C源码与313个头文件涵盖HAL库驱动、USB协议栈、Flash操作及DAPLINK核心逻辑辅以汇编启动文件、Keil工程配置.uvprojx/.uvoptx、调试脚本bat及烧录用bin固件总大小2.78MB。已有2302人下载学习适用于需掌握ARM Cortex-M3平台固件定制、SWD调试接口二次开发及JLink RTT高效日志输出的实践场景。资源提供开箱即用的Keil5工程结构已集成RTT初始化与打印接口预置stm32f103xb_stm32f103rb_if_crc.bin烧录镜像并包含usb_lib.c、fsl_flash.c、stm32f1xx_hal_uart/spi/i2c/tim/usart/sd等关键外设驱动适配代码显著降低移植门槛与排错成本。 先说说我为什么会折腾这个东西。手头有一颗放了很久的STM32F103RCT6LQFP64封装、512KB Flash、64KB SRAM闲着也是闲着干脆做成一个DAPLink调试器。DAPLink这个方案的好处不用多讲开源、不用买授权、一条USB线同时搞定下载和虚拟串口还支持拖拽烧录。比起手里那几个J-Link成本几乎可以忽略。但折腾完DAPLink之后我又发现一个问题日常调试时用惯了RTT Viewer看日志DAPLink本身没法直接被RTT Viewer识别于是就有了这一篇——用F103RCT6把DAPLink跑起来再在Keil5工程里把SEGGER RTT打印彻底打通。这篇内容不是单纯贴个固件链接让你抄作业而是把“DAPLink固件移植”“Keil5工程配置”“RTT代码集成”“RTT Viewer连接”这条链路完整讲清楚。适合手里有F103系列开发板、想自己做调试器的人也适合那些已经在用DAPLink但被RTT Viewer挡住的人。1. 这个项目到底在做什么自研DAPLink再解决RTT打印1.1 DAPLink的本质与优势DAPLink是ARM官方开源项目跑在Cortex-M内核的MCU上对外模拟出一个CMSIS-DAP调试器。电脑端用Keil、IAR、pyOCD等工具通过USB访问它它再通过SWD接口读写目标芯片。本质上就是给一颗普通MCU刷一个固件让它变成“调试器”。用F103RCT6做宿主芯片非常合适。它的SWD接口引脚和USB外设都是现成的512KB Flash对DAPLink固件来说绰绰有余64KB SRAM也足够做缓冲。DAPLink的优点还在于它同时提供USB虚拟串口功能下载完程序直接打开串口助手就能看printf输出不需要额外接USB转TTL模块。这一点在实际开发里非常方便尤其是调试一些没有板载串口芯片的目标板时。有人会问既然有J-Link为什么还要折腾DAPLink我的理由是J-Link固件不开源、授权限制多而DAPLink完全开放你可以根据自己的板子改引脚、改LED、甚至做批量烧录工具。这个项目做完之后等于手里多了一个不受限制的调试器。1.2 RTT不是J-Link专属但RTT Viewer是SEGGER RTT是J-Link调试器配套的一种日志方案。和串口打印不同RTT通过调试器的SWD接口直接读取目标芯片内存里的环形缓冲区不需要占用UART引脚速度快、不影响实时性。目标工程里只要加入SEGGER RTT源码并调用打印函数数据就会写入内存缓冲区调试器侧的程序再从缓冲区读出来显示。这里要弄清楚一个容易混淆的点RTT协议本身是开放的目标芯片上的SEGGER_RTT代码可以放进任何工程不要求你必须用J-Link。但SEGGER官方的RTT Viewer上位机软件默认只支持J-Link它不认CMSIS-DAP设备。也就是说当你用自制DAPLink做调试器时RTT代码照常可以跑但RTT Viewer这一层软件无法直接连上DAPLink。所以严格来说“DAPLink环境下使用RTT Viewer”是不成立的。靠谱的做法有三条路一是额外配一个J-Link专门看RTT二是放弃RTT Viewer直接用DAPLink的USB虚拟串口看打印三是用支持RTT的开源工具链绕过SEGGER上位机。后面会详细说。1.3 整体链路从固件到打印需要走通哪些环节完整方案涉及“调试器侧”和“目标板侧”两部分。调试器侧就是F103RCT6刷DAPLink固件它提供一个CMSIS-DAP调试接口和一个USB虚拟串口目标板侧是你要调试的STM32或其他Cortex-M芯片工程里加入SEGGER RTT源码通过SWD连到调试器。Keil5在中间扮演的角色有两个一是作为DAPLink固件的编译环境二是作为目标板工程的开发调试环境。本文标题是“基于STM32F103RCT6移植DAPLinkKeil5工程添加J-Link RTT Viewer打印”实际操作时就是先在Keil5里把DAPLink固件编译烧录好再在Keil5里建目标工程并加入RTT代码最后用RTT Viewer观察输出。2. 移植DAPLink到STM32F103RCT6源码、工程、烧录2.1 准备DAPLink源码先判断官方工程能不能直接用DAPLink官方源码在GitHub的ARMmbed/DAPLink仓库里。官方维护的目标板列表很长但STM32F103并不是官方主推平台很多是社区贡献的移植。比较稳妥的做法是先拉官方源码看看里面有没有现成的F103RC配置如果没有再考虑自己适配或使用社区已经验证过的分支。如果你只想快速得到一颗能用的调试器直接下载别人编译好的F103 DAPLink固件hex文件烧进去就可以GitHub上搜“daplink stm32f103”能找到不少。但既然是“移植”我建议还是把源码编译路径走一遍。新版的DAPLink源码使用Python脚本生成工程文件大致流程是安装Python和依赖库然后在源码根目录执行构建脚本指定目标芯片型号生成对应工程。具体target名称和命令在仓库的docs目录里有说明不同版本略有差异。如果你习惯直接改工程也可以找社区维护好的Keil工程模板比从零适配省事很多。我实际折腾时的感受是F103RCT6和常见的F103C8在DAPLink适配上有不少共通之处引脚定义、flash大小、RAM大小不同但移植逻辑是类似的。核心要改的地方有三个Flash和RAM的起始地址与大小、SWCLK/SWDIO引脚和LED引脚配置、USB相关的时钟配置。2.2 Keil5工程搭建与关键配置编译DAPLink固件时Keil5的工程配置有几个容易踩坑的地方。首先是芯片选择。Keil5新装后默认没有STM32F1系列支持需要先安装Device Family Pack。打开Pack Installer搜索“STM32F1”安装Keil.STM32F1xx_DFP。这一步没做的话新建工程时芯片列表里根本找不到STM32F103RCT6。其次是编译器版本。DAPLink很多老工程是用ARM Compiler 5编译的而新装的Keil5默认可能只带ARM Compiler 6。如果你打开工程后直接编译很可能报错提示找不到“default compiler version 5”。解决办法是在Project - Manage - Project Items - Folders/Extensions里添加ARM Compiler 5.06的安装路径或在Options for Target里把编译器版本切到V5。AC6对老代码的兼容性比较差尤其是内嵌汇编、位域操作比较多的底层代码不建议硬用AC6。然后是宏定义和启动文件。F103RCT6是512KB Flash、64KB SRAM如果从F103C8工程改过来一定要检查器件宏是否还指向F103C8同时确认启动文件用的是startup_stm32f10x_hd.s高密度而不是md.s或ld.s。启动文件选错会导致烧录后程序跑飞而且这种问题不容易一眼看出来。注意DAPLink固件里通常会区分“bootloader”和“interface firmware”。如果你编译的是完整版固件而不是分体式bootloaderapp结构烧录后只有一个设备如果固件分两个部分务必先烧bootloader再烧app顺序反了可能无法进入USB烧录模式。2.3 硬件准备与引脚分配F103RCT6跑DAPLink固件需要把以下引脚接好功能引脚说明USB D-PA11USB差分信号负端USB DPA12USB差分信号正端SWDIOPA13调试目标板的SWD数据线SWCLKPA14调试目标板的SWD时钟线LED视固件而定调试器状态指示灯源码里可配置如果你的板子上已经有USB口直接连到F103的PA11/PA12即可。要注意的是USB需要48MHz时钟F103的USB外设无法直接从内部HSI获得精确时钟板子上一定要有8MHz外部晶振否则USB可能枚举不稳定甚至完全无法识别。SWDIO和SWCLK引脚通常直接复用到PA13/PA14不用额外改除非你的固件里做了别的映射。LED引脚常常被改成开发板上的板载LED如果你用的板子LED不在源码默认引脚上记得查找源码中LED_CONNECTED、LED_RUNNING这类宏并改到实际引脚。2.4 烧录固件并验证设备识别第一次烧录DAPLink固件时目标芯片本身还是空的没有USB调试器可以用。常见办法是串口ISP烧录把F103RCT6的BOOT0拉高、BOOT1拉低通过UART1接USB转TTL模块用FlyMcu或STM32CubeProgrammer把hex文件烧进去。烧完后把BOOT0拉低复位运行。如果你有其他调试器也可以用SWD烧录速度更快。烧录成功后插上USB线Windows设备管理器里应该出现两个设备一个调试设备CMSIS-DAP v2或DAPLink CMSIS-DAP一个虚拟串口设备通常显示为USB Serial Device或Mbed Serial Port。如果只出现未知设备或没有任何反应优先检查USB时钟晶振和R14/R22之类USB D上拉配置。F103的USB D需要外部1.5k上拉电阻到3.3V这个在自制板上很容易被忽略。3. 在Keil5目标工程里加入SEGGER RTT从源码到首行打印3.1 获取SEGGER RTT源码并添加到目标工程SEGGER RTT源码并不需要额外购买安装J-Link软件后可以在安装目录里找到路径一般是C:\Program Files\SEGGER\JLink\Samples\RTT。里面包含的文件不多核心是SEGGER_RTT.c、SEGGER_RTT.h、SEGGER_RTT_printf.c、SEGGER_RTT_Conf.h和SEGGER_RTT_ASM_ARMv7M.S。把这些文件复制到目标工程目录下添加到Keil工程中。我的建议是放到一个独立的RTT文件夹里而不是和主代码混在一起后续升级替换也方便。头文件路径记得在Options for Target - C/C - Include Paths里添加否则编译时报找不到头文件的错。这里补充一句RTT源码对编译器要求不高AC5和AC6都能编不像DAPLink固件那么挑编译器。目标工程如果是AC6正常添加即可不需要额外处理。3.2 代码集成初始化、RTT_printf与stdio重定向在main函数开始时调用SEGGER_RTT_Init();这个函数会初始化RTT控制块和缓冲区不调用的话首次打印时内部也会自动初始化但显式调用更稳妥尤其是在使用多通道或者需要自定义缓冲区大小时。打印方式有两种。第一种是直接用官方提供的格式化函数SEGGER_RTT_printf(0, count %d, temp %.2f\n, count, temp);第二个参数开始就是普通的printf格式串用法和标准C库基本一致。通道0是默认的上行通道平时调试看日志用这个就够。第二种方式是把printf重定向到RTT。这样你原来代码里所有的printf都不用改输出自动走RTT通道。在Keil中需要实现fputcint fputc(int ch, FILE *f) { SEGGER_RTT_PutChar(0, ch); return ch; }注意Keil的微库选项。如果勾选了MicroLib重定向fputc的写法跟标准库略有区别但核心思路一样。我在实际项目中习惯只保留SEGGER_RTT_printf不用printf重定向因为RTT本身有自己的格式化和性能优势重定向之后还要考虑缓冲区和格式串的兼容问题。3.3 RTT Viewer连接目标板J-Link场景下的标准操作如果你的调试器是J-Link这一步非常简单。先把目标板程序跑起来再打开J-Link RTT Viewer软件会自动弹出一个连接对话框。选择USB连接目标芯片选STM32F103RC接口选SWD速度默认即可点OK后如果能自动找到RTT控制块直接就能看到打印输出。如果RTT Viewer提示找不到RTT控制块可以手动指定控制块地址。在Keil编译生成的map文件里搜索_SEGGER_RTT会看到一个类似这样的行_SEGGER_RTT 0x20000010 Data 296这个0x20000010就是控制块地址。在RTT Viewer的连接设置里选手动地址把这个值填进去重新连接就能识别。注意RTT Viewer和Keil的调试器不能同时占用同一个J-Link。如果你在Keil里已经进入调试模式再打开RTT Viewer连接同一个J-Link后一个进程通常会被挡在外面。正确顺序是先下载程序并运行退出Keil调试模式再启动RTT Viewer。3.4 DAPLink配合RTT的三种落地方式这一节算是全文最核心的实战经验。很多人在网上问“为什么我的DAPLink用不了RTT Viewer”答案其实很简单RTT Viewer不识别CMSIS-DAP协议。DAPLink的目标芯片内存里确实有RTT控制块SWD接口也能读内存但SEGGER上位机只跟J-Link通信所以连不上是必然的。第一条路双调试器方案。DAPLink负责下载和Keil在线调试另外接一个J-Link哪怕是一块便宜的J-Link OB到目标板的SWD接口RTT Viewer连J-Link看打印。目标板的SWD三根线可以同时接着两个调试器只要做到同一时刻只有一个设备在操作目标芯片就不会冲突。下载时用DAPLink烧完退出Keil调试再用J-Link的RTT Viewer连接看RTT输出。这个方案最符合标题里“J-Link RTT Viewer”的字面意思也最稳定代价是手上得多一个J-Link。第二条路用DAPLink虚拟串口平替。DAPLink自带USB虚拟串口目标板程序里不写RTT改用UART输出printf通过DAPLink的虚拟串口在电脑上看。这个方案没有RTT那种“不占UART引脚”的优势但胜在零额外成本而且用串口助手就能看团队协作时别人也容易上手。如果只是想看日志其实串口完全够用。第三条路使用支持RTT的开源工具链。pyOCD和OpenOCD在新版本里都对RTT做了支持它们都能识别CMSIS-DAP设备。用OpenOCD启动调试器时可以开启RTT服务器把RTT数据转发到本机端口再用支持网络连接的RTT客户端读取。这个方案配置稍微复杂一点但不需要J-Link适合喜欢命令行解决问题的玩家。我自己的建议是日常调试主力用DAPLink虚拟串口简单可靠如果项目对实时日志有很高要求需要低延迟看大量RTT数据再加J-Link走RTT Viewer。毕竟RTT的强项是不打断程序执行串口打印在高频中断里会影响时间得看场景取舍。4. 常见问题与排查实录4.1 DAPLink不被Keil识别或下载失败Keil里选择调试器时在Options for Target - Debug的右侧下拉框里选“CMSIS-DAP Debugger”然后点Settings如果Device框里能看到DAPLink设备说明连接正常。如果列表是空的先看设备管理器里调试器有没有被识别没识别就检查USB线和上拉电阻识别了但Keil看不到多半是驱动问题重新安装CMSIS-DAP驱动或重启Keil后再看。下载失败还有一种常见情况目标板SWDIO和SWCLK接线接反或者目标板供电不足。DAPLink的SWD接口一般不需要额外给目标板供电但如果目标板是独立供电记得共地否则SWD时序不稳定经常报“Cannot access target”。4.2 RTT Viewer找不到RTT控制块这个问题分两种情况。一种是目标程序还没运行RTT控制块还没有被写入内存RTT Viewer当然找不到。解决方法是先让程序跑起来再打开RTT Viewer连接。另一种是程序已经在运行但RTT控制块地址不在RTT Viewer自动扫描的范围内。解决办法就是前面说的在map文件里找_SEGGER_RTT地址手动填写。此外如果目标芯片的RAM很大自动扫描可能需要较长时间可以在RTT Viewer设置里缩小搜索范围或者直接把搜索地址范围上限调到目标RAM末尾附近。4.3 打印乱码、缓冲溢出与触发中断冲突打印乱码最常见的原因是通信波特率不匹配但RTT用的是内存缓冲不走波特率所以如果RTT打印乱码多半是地址填错读到了错误的内存区域。另一个可能是RTT Viewer里选择的芯片型号不对导致内存映射判断错误。RTT缓冲溢出比较隐蔽。默认上行缓冲区大小是1024字节如果程序一次性打印大量数据或者在一个高频循环里疯狂打印缓冲区塞满后新数据会被丢弃。在SEGGER_RTT_Conf.h里可以调整BUFFER_SIZE_UP打印多就改大。但也不要无脑改大缓冲区占用的是RAM空间F103RCT6虽然有64KB RAM但其他功能也要用。关于中断冲突SEGGER_RTT_printf内部不是完全可重入的如果在中断和主循环同时调用同一个通道打印可能出现数据错乱。RTT本身的使用场景是日志输出建议只在主循环或低频任务里打印不要在中断服务函数里频繁调用。如果确实需要在中断里打印优先用SEGGER_RTT_WriteString并且注意临界区保护。4.4 Keil5编译器版本与Pack包相关报错之前提到“uses arm-compiler default compiler version 5 which is not available”这个报错在新装Keil5后非常常见。原因就是你安装的MDK版本只带了AC6但工程配置里指定用AC5编译。解法有三种安装Arm Compiler 5在工程属性里把编译器切换到AC6如果代码兼容或者同时安装C51和MDK时注意两者共用IDE但从ARM官网下载的AC5安装包可以单独装到Keil目录下然后在MDK里识别出来。另外还有一类报错是打开工程后芯片型号是空的或者编译提示找不到“pack”这就是STM32F1xx_DFP没装好。打开Pack Installer在Devices列表里找到STM32F1系列点Install等装完再编译。经验之谈DAPLink固件编译和普通应用程序编译最好用两个独立的Keil工程不要混在一起。DAPLink工程依赖老版本GCC或AC5的特性目标板工程可能又需要AC6的新特性硬塞到一个工程里只会让问题复杂化。5. 写在最后几条个人经验这里分享几个我实际踩过坑之后总结的习惯。第一DAPLink固件烧录前先把原芯片的BOOT0跳线方式确认好。F103的BOOT0默认是拉低从Flash启动ISP烧录时要拉高这个操作很常规但每次都要查跳线帽位置很浪费时间。我后来直接做了个小板子把BOOT0和复位按键引出来切换明显方便很多。第二RTT的调试方向很值得投入但不要把它当成唯一选择。我见过不少人为了RTT Viewer把整个工程折腾到不行最终还是回到串口打印。调试工具永远是辅助稳定性优先。先用DAPLink的虚拟串口跑通业务逻辑再按需引入RTT这个顺序更合理。第三DAPLink不只是给STM32用的。它的SWD接口本身是通用的Cortex-M调试口只要目标芯片支持SWDKeil里装好对应芯片的DFP就能下载调试。最近有人在用DAPLink配CW32L010开发也是同样的道理下载、看串口打印、在线调试全都能用这充分说明自制DAPLink的价值不局限于某个芯片型号。最后如果非要在“DAPLink加RTT”这条路上走下去我建议你把手里的J-Link留着哪怕只是一个最便宜的J-Link OB。RTT Viewer这个工具确实好用它和J-Link的组合是SEGGER生态里最成熟、坑最少的一套方案。不折腾、好维护本身也是一种工程能力。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价