ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Keil uVision5烧录STM32全攻略:从ST-Link配置到常见报错排查

Keil uVision5烧录STM32全攻略:从ST-Link配置到常见报错排查 玩单片机这几年我一直在用Keil写STM32的代码。别看现在大家动不动就提各种新工具链实际工作里最常用的还是Keil uVision5。当年我刚开始接触STM32时用的就是Keil v5.11这个版本配合ST-Link给板子烧录程序前前后后折腾了不少时间把开发环境、调试器驱动、烧录配置、报错处理挨个试了一遍才理顺。这篇文章就把这整个过程记录下来包括一些容易踩的坑和排查思路希望对正在用Keil给STM32烧录程序的你有所帮助。1. 烧录前的硬件和调试器准备把“看不见的连接”先捋清楚1.1 调试器选型ST-Link、J-Link、CMSIS-DAP到底用哪个Keil本身不是烧录器它只是个编译加调试的IDE真正把程序写进STM32内部Flash的是外接的调试器。对STM32来说常见的调试器有三种官方的ST-Link、SEGGER的J-Link还有各种开源的CMSIS-DAP调试器。我最初用的是ST-Link V2二十来块钱一个的普通版本正面印着ST的Logo实际用下来烧录F103、F407这些芯片完全够了。ST-Link的好处是官方对STM32支持最透彻跟Keil配合时需要装的驱动也就是ST-Link USB Driver。装好驱动后插上USBWindows设备管理器里应该能看到一个ST-Link dongle或者STLink dongle这样的设备看不到就检查驱动。J-Link的烧录速度更快尤其是对大容量Flash芯片而且它自带J-Flash工具可以单独用来烧录程序。但J-Link的正版价格不低市面上一两百的盗版J-Link V9/V11在Keil里用偶尔会出现固件升级不兼容、掉线的问题。如果你刚开始学用ST-Link最省心。CMSIS-DAP是ARM做的一个开源调试协议实现很多国产开发板自带的调试器就是这个方案。它的好处是免驱、开源、便宜坏处是不同的CMSIS-DAP实现质量参差不齐有的在Keil里识别不稳定。常用方法是Debug页面的调试器下拉栏里选CMSIS-DAP Debugger。选哪种没有绝对答案我给个选择逻辑只玩ST官方芯片就选ST-Link需要高速烧录配合J-Flash用就选J-Link买了国产开发板且板载调试器是CMSIS-DAP就先用自带的。1.2 SWD接线与供电顺序决定烧录稳定性的细节调试器和芯片之间走的是SWD协议标准接线是四根SWDIO、SWCLK、GND、3.3V可选。SWDIO对应STM32的PA13SWCLK对应PA14这个不用死记只要知道这组引脚是芯片专门留给调试器用的就行。很多人烧录失败的第一原因就出在杜邦线上。我用过的STM32最小系统板引脚间距是2.54mm杜邦线一插就是六根八根时间一长线序难免出错。苏这里的建议是不要用不同颜色的杜邦线去猜直接在板子上找丝印标注的SWDIO、SWCLK、GND、3V3一一对应插好。带电插拔调试线我也干过一次ST-Link没坏板子也没烧但不代表安全正确做法是断电状态下接线再上电打开Keil。供电这个问题也比较容易出岔子。给目标板供电的方式有三种USB口供电、外部稳压电源供电、调试器ST-Link输出的3.3V供电。ST-Link V2的3.3V输出电流只有几十到一百毫安左右带个跑马灯的小板子没问题带一块带屏幕、传感器、电机驱动的系统板就力不从心会出现上电后芯片复位反复、烧录中途掉线等情况。所以只要板子上有独立的USB供电口或电源接口就优先用外部供电调试器只管传输数据。1.3 特殊情况的BOOT0和复位电路烧录程序还涉及一个经常被忽视的引脚BOOT0。STM32的启动模式由BOOT0和BOOT1引脚的电平决定从系统存储器启动BOOT0拉高时可以用来通过串口ISP方式烧录程序。但是用Keil加调试器烧录时芯片必须处于从主Flash启动的状态也就是BOOT0要接GND。有些开发板为了让用户方便ISP下载做了一个BOOT0的跳线帽或拨码开关。如果你手上有板子的BOOT0被拨到了1高电平Keil里点击下载时就会提示Cannot access target因为芯片根本没有从Flash启动调试器是无法控制它的。我第一次遇到这个问题时还以为是板子坏了检查了半天才发现是BOOT0拨码位置不对。复位电路对烧录的影响没有启动模式那么致命但如果板上复位引脚悬空或者复位电容取值不对芯片可能出现上电后一直在复位状态的情况此时调试器也连不上。标准做法是NRST引脚接一个10kΩ上拉电阻到3.3V再接一个0.1μF电容到GND正常情况下NRST是高电平低电平触发复位。板子正常工作后不用过多关注但如果出现“连不上目标”“写Flash时芯片复位”的诡异现象可以顺手测一下NRST电平。2. Keil v5.11工程里的烧录配置打开工程只是开始2.1 芯片型号与Device Pack的匹配Keil能把程序烧给STM32前提是它知道这颗芯片的Flash容量、RAM大小、外设地址等信息这些信息集中在Device Pack里。STM32F1系列用的是Keil.STM32F1xx_DFP包STM32F4系列用的是Keil.STM32F4xx_DFP包选错了或没装工程目标芯片那一栏会显示空白或一个感叹号编译链接都可能报错。我在装Keil v5.11那会儿Pack包是要手动从官网下载的不像现在新版Keil自带Pack Installer一键安装。如果你遇到Keil的Pack Installer联网很慢或者一直卡在“检查更新”界面可以直接去ARM的CMSIS Pack页面下载对应DFP的pack文件然后双击安装Keil会自动识别并解包。离线安装的好处是版本可控比如你想固定用某版DFP不让它随便升级离线包就是最好的方案。装好Pack后在Options for Target的Device选项卡里能找到STMicroelectronics目录树展开后选择具体的芯片型号比如STM32F103C8、STM32F407ZGT6。这里有个容易忽略的点同一个芯片后缀不同内部Flash和RAM可能不一样比如C8的是64KB FlashCB的是128KB Flash。如果选错Keil虽然能编译出程序但烧录时的地址和算法可能会不匹配轻则烧录失败重则程序跑飞。选芯片型号这一步看似简单但它决定了后续Flash Download算法能否正确匹配是绕不过去的。2.2 Debug页面的调试器选择和参数芯片型号选对后接下来要进Options for Target切换到Debug选项卡。这里默认选的通常是Use Simulator你要改成Use: ST-Link Debugger或你实际用的J-Link、CMSIS-DAP。这个操作漏掉的后果就是Keil不识别外部调试器点击Download时会提示Could not reset the target或Cannot access target。选好调试器后点击旁边的Settings按钮会弹出调试器设置窗口。这里有几个关键参数Port选SW。STM32基本都用SWDJTAG方式虽然也行但占用的引脚多现在基本不推荐。Max Clock默认可能是4MHz或5MHz。如果你用的是杜邦线加面包板走线较长且没有屏蔽建议降到1MHz或更低。SWD的时钟频率和稳定性成反比频率太高时容易在校验环节随机报错。如果看到SW Device那里能识别出一串IDCODE比如STM32F1常见是0x1BA01477或0xBB11477之类的说明调试器和芯片的物理链路是通的。识别不出来就说明接线、供电、芯片启动模式有一个环节不对。这个Settings窗口是烧录排查的分水岭能识别出SW Device说明硬件链路没问题问题多半在软件配置识别不出那就老老实实回到上一节检查硬件。我在后面的报错排查部分会再展开讲这个思路。2.3 Flash Download擦除、校验、复位和运行Debug设置好后另一个跟烧录直接相关的是Utilities选项卡。默认情况下Keil会勾选Use Debug Driver意思是烧录操作直接复用刚才选择的调试器。这个保持默认就行。真正的设置重点在点开Settings按钮后的Flash Download页面。Flash Download页面的几个选项要按实际需求勾选Download Function里的Erase Full Chip和Erase Sectors前者是全片擦除后者是擦除程序占用的扇区。如果你程序里用到了芯片内部Flash存储了一些掉电保存的数据建议用Erase Sectors避免全片擦除把存储区的数据也清了。Program和Verify默认勾选一个负责写入一个负责读回校验。校验能及时发现写入过程中的坏块或通信异常。烧录完显示“Flash Load finished”不代表一定成功只有Verify通过才算真正写对了。Reset and Run勾选后烧录完自动复位运行不勾选的话烧录完芯片停在停机状态程序不会立即跑起来。多数情况下我都会勾上烧完就能看到现象省去手动按复位键的步骤。Flash Download另一个核心是下方的Programming Algorithm列表。Keil会根据芯片型号自动添加对应的Flash算法。比如STM32F103C8会添加STM32F10x Med-density Flash 64kBSTM32F407ZGT6会添加STM32F4xx Flash 1MB。如果你发现这个列表是空的烧录时一定会报错Cannot Load Flash Programming Algorithm。解决办法有两种重新选择正确的芯片型号或者手动点击Add按钮在列表里找到匹配的Flash算法添加进去。还要注意起始地址。STM32内部Flash的起始地址统一是0x08000000但RAM的起始地址根据不同系列可能是0x20000000F1/F4都是。Flash Download设置里的Start地址一般就是0x08000000别改成别的地址。曾经有人在设置里不小心改成了0x8000000少写了一个0结果烧录出来的程序完全跑不起来因为地址超出了Flash物理范围。3. 烧录过程中最常踩到的四类报错3.1 No target connected九成是接线或供电问题No target connected是烧录时最经典也最常见的一类报错英文的提示通常是No target connected中文环境下可能显示“没有连接到目标”或Cannot access target。出现这个错误时第一反应不要去看代码代码编译都通过了问题在物理链路。按下CTLF5或Download按钮后如果Keil一直卡在Connecting to target几秒后弹窗报错先做三件事检查SWDIO和SWCLK是否接反。这个占了我遇到的一半以上问题特别是用不同颜色的杜邦线时很容易把两根信号线插反。给板子重新上电。调试器有时会处于半连接状态把板子的USB拔掉重新插让芯片彻底复位一次。把Debug设置里的Max Clock从4MHz降到1MHz。有些老杜邦线在高频下信号反射严重SWD握手就失败了。一个有效的判断方法把杜邦线长度尽量缩短到10厘米以内进行测试。如果短线上没问题、长线上有问题说明是信号完整性问题而不是芯片和调试器坏了。减少线长后一般能解决。3.2 RDDI-DAP Error和芯片锁死问题RDDI-DAP Error这个报错比较邪门字面意思是“远程调试数据接口-调试访问端口错误”。我在网上查了很多资料最后发现它出现在两种典型场景。第一种是调试器驱动和Keil版本不兼容。比如你电脑上装了较新版本的ST-Link驱动又用着老版本Keil就可能出现RDDI-DAP Error。解决办法是卸载较新的ST-Link驱动装回Keil v5.11配套驱动如果不行就在Debug设置里把调试器换成ST-Link再换回来强制重新初始化。第二种跟芯片状态有关。芯片内部的调试接口被禁用或者芯片进入了休眠模式调试器就无法访问DAP端口。有些低功耗项目会配置DBGMCU寄存器来关闭调试时钟程序一旦跑起来就把调试端口关了下次烧录就会出现RDDI-DAP Error。解决方法是进入系统存储器模式也就是把BOOT0拉高从ISP区启动这样芯片不会执行用户程序调试接口自然恢复。还有一种跟芯片锁一个字错误提示里包含RDDI-DAP Error且无论怎么试都无法连接时多半是芯片内部的Flash Lock被开启了。STM32的读保护Level 1开启后通过SWD只能读出IDCODE不能执行擦除和写入Keil会直接报RDDI-DAP错误。解除办法是用ST-Link Utility的Connect under reset模式在芯片复位瞬间强制连接然后执行Mass Erase擦除整个Flash。这个方法能救回大多数被读保护锁住的芯片。但如果开了Level 2读保护那是硬件级的没法再通过SWD解锁基本就废了这点一定要谨慎。3.3 Flash Download失败算法、地址和时序烧录过程走到一半进度条卡在Erasing...或Programming...时报错常见的错误信息有Flash Download failed - Target DLL has been cancelled、Cannot Load Flash Programming Algorithm、Flash Timeout. Reset the Target and try it again。Cannot Load Flash Programming Algorithm十有八九是芯片型号没选对导致Flash算法列表为空或不匹配。我见过有人在STM32F103芯片的工程里换用STM32F030芯片Keil没自动更新算法仍保留旧的F1算法就会报这个错。处理方式就是把算法列表删干净重新Add正确的算法。Flash Timeout这个报错比较隐蔽通常出现在SWD时钟频率过高时。Flash写入有自己的时序要求如果SWD通信不稳定导致调试器发送的写命令没有在预期时间内完成Keil就会报超时。解决办法首先是降速到1MHz以下其次检查板子供电是否充足Flash写入对电压比较敏感电源纹波大时容易失败最后还有一种情况是目标芯片的Flash写保护引脚或其他复用功能影响了Flash控制器的工作需要看具体芯片的参考手册。Target DLL has been cancelled这个报错一般不认为是板子的问题反而更像软件层面的卡死。常见于Keil与杀毒软件、其他调试软件冲突时。我用过STM32CubeProgrammer同时连接同一个ST-Link就会出现调试器被占用、烧录一半被取消的情况。解决办法是关掉可能占用调试器的其他软件再重新执行烧录。另外如果你在Keil烧录的同时开着多个Keil工程窗口也可能出现这个问题一次只开一个项目烧录最稳。3.4 Pack安装中的“硬件错误”包管理器本身的bug热搜词里有一个“keil pack install 硬件错误”我猜是Pack Installer弹了一个“hardware error”或类似提示的报错。这里说的“硬件错误”不是硬件坏了而是Pack Installer在更新或安装过程中出现的异常常见的原因是什么一是网络问题。Pack Installer默认从Keil官网下载国内网络经常连不上或者下载到一半断流就会报安装失败。解决办法是切换到离线安装方式手动下载pack文件双击安装绕过在线包管理器。二是Keil版本和Pack版本不兼容。Keil v5.11算是比较老的版本而新版的STM32F4xx_DFP要求的新版本Keil可能不支持。这时最好找一个与你Keil版本年代相近的旧版Pack不要一上来就装最新版。在ARM Pack页面会显示每个Pack版本对应的Keil兼容性范围选一个Published时间接近你Keil版本的就好。三是权限问题。Keil安装在C盘Program Files下时Pack包的安装路径可能没有写权限导致安装到一半报错。解决办法是右键点击Keil图标选择“以管理员身份运行”然后再安装Pack或者把Keil整个安装目录移到用户可写的位置。遇到过这些情况后我现在装Pack包的习惯是先离线下载pack文件双击后等它显示“Install Successful”才继续下一步尽量避免在线安装带来的不确定性。4. 烧录成功后的验证手段和提速技巧4.1 程序跑没跑起来用调试断点和状态灯判断烧录过程最终显示Application running或Verify OK并不代表程序就一定正确运行了。芯片可能跑飞、可能进了HardFault、可能时钟配置不对导致外设初始化失败。所以烧录成功后还要做验证。最直接的办法是进入Keil的Debug模式CtrlF5。调试器连接成功后程序会停在main函数的入口或者停在SystemInit之前此时你可以单步执行看每一行代码的执行结果是否符合预期。如果程序执行时就跳到HardFault_Handler多半是数组越界、指针地址非法、外设时钟未开启等问题需要在代码里排查。没有调试器或者不方便仿真时状态灯是第二选择。烧录一个最简单的GPIO翻转程序让PC13引脚或者板上LED对应的引脚输出高低电平交替。如果LED按预期闪烁说明芯片内核、时钟、基本GPIO配置都没问题。这个“最小点灯程序”屡试不爽我用它排除过很多模糊问题芯片没坏、晶振没坏、电源没坏、烧录确实成功了。4.2 读取Flash校验和彻底擦除的方法Keil烧录完成时的Verify是对比写入内容和目标文件中程序段的内容只要写进去的二进制和Hex/AXF一样Verify就通过。但有时候你怀疑ST-Link把数据写到别的扇区了或者之前的旧程序残留影响运行就需要手动做一次真正的读回校验。你可以用ST-Link Utility官方免费工具连接芯片后点击Read Back把整个Flash内容导出成一个.bin文件然后和你Keil编译出的.bin文件做二进制对比。如果两者完全一致那就是真·烧录成功。如果不一样就要检查Flash下载设置里的起始地址和芯片型号了。彻底擦除还有一种情况芯片里Flash的某些扇区处于写保护状态擦除时Keil会报错。这时用ST-Link Utility里的Mass Erase可以忽略扇区保护全片擦除一遍然后再回Keil烧录。这个流程适用于芯片从别的项目板子上拆下来的场景或者程序里使用过Flash扇区写保护的场景都很管用。4.3 频繁烧录时我常用的一些提速技巧如果你在调试阶段免不了半天烧几十次甚至上百次程序有一些提速技巧很实用。第一关闭不必要的Target输出文件。在Options for Target的Output选项卡里Keil默认会生成AXF文件如果你不勾选Create HEX FileKeil烧录时所用的目标文件是AXF。AXF里包含调试信息文件体积比Hex大不少但对于烧录来说更全。如果项目比较小这个差别不大如果项目很大勾选Create HEX File并让烧录时以Hex为源有时候会快一些。注意切Hex烧录时Flash Download里的Verify还是要勾的。第二使用Erase Sectors代替Erase Full Chip。调试过程中每次只修改了部分代码一般只影响少量扇区用Erase Sectors可以省去全片擦除的时间。我在一个100KB的项目上实测全片擦除加写入要十几秒扇区擦除加写入只要三四秒。当然如果你改了链接脚本、向量表偏移或者Flash占用位置有变化该全片擦还是全片擦不要在这个地方省。第三烧录时把View窗口全部关掉。Keil在Debug模式下如果开着反汇编窗口、寄存器窗口、Watch窗口每次烧录都要刷新这些视图拖慢速度。纯下载时我习惯直接按F7编译编译完按F8下载我的个人按键映射是把Download映射到F8全程不打开Debug模式速度最快。第四对于频繁烧录的板子尽量固定使用同一个ST-Link避免电脑识别新的USB设备导致驱动重装。我有一块ST-Link专门用于调试另一块专门给烧录用两块在不同的USB口上插着Keil里配置好对应的调试器序号这样换板子时基本不会出现调试器冲突。5. 烧录用到的辅助工具和资源J-Flash与ST-Link Utility的分工5.1 J-Flash适合什么样的烧录场景虽然这篇博客主要讲Keil烧录但很多人在烧录这条路上还会接触到J-Flash。J-Flash是SEGGER J-Link配套的烧录工具它能烧录的芯片范围很广不只是STM32。用J-Link时J-Flash会先要求你选择芯片型号然后选择要烧录的Hex或Bin文件设置起始地址点击Program就完成烧录。跟Keil相比J-Flash的优势是对大容量Hex文件的烧录速度快而且可以读回、擦除、编程独立操作不依赖编译环境。如果你手头有一个Hex文件想快速烧到板子里不想打开KeilJ-Flash是一个好选择。J-Flash的问题是它的GDB Server和Keil的调试器会争用J-Link如果你用J-Flash烧录完后没有断开连接回Keil里点击Download就可能报调试器被占用。5.2 ST-Link Utility在烧录流程中的定位ST-Link Utility是ST官方给ST-Link配套使用的PC工具它支持在线烧录、读回、擦除、选项字节修改、ST Online Upgrade固件升级等功能。对Keil烧录来说ST-Link Utility最好用的地方在于“救砖”和“改选项字节”。前面提到的RDDI-DAP Error芯片解锁、读回校验、全集擦除我都是先用ST-Link Utility处理的处理完再回到Keil做正常烧录。如果你的芯片开启了读保护Keil里很可能连擦除都做不了但ST-Link Utility如果连接能力更强一点有时候能直接解锁。注意新版ST的STM32CubeProgrammer已经在逐渐取代ST-Link Utility功能类似如果你手头已经装了CubeProgrammer用它也行没必要再装一个Utility。5.3 Keil与外部工具的联动烧录流程在一些量产或半量产场景里并不会直接用Keil GUI烧录因为操作界面不够自动化。常用的做法是先用Keil编译生成Hex文件再通过命令行调用外部工具进行批量烧录。比如用ST-Link的命令行工具STM32_Programmer_CLI或者J-Link的JLink.exe脚本烧录这些工具都能在无人值守的情况下完成烧录。但如果只是个人开发调试还是Keil图形界面最省事。我发现一个比较实用的组合平时用Keil的Download直接烧录遇到需要读回或解锁的杂症才打开CubeProgrammer或ST-Link Utility处理一下两个工具各管一段分工明确。你不要指望Keil把所有烧录场景都干了它做得最好的还是“编译集成一体的快速下载”。6. 给初学者的烧录操作流程总结6.1 从新建工程到完成烧录的完整步骤清单把前面讲的内容浓缩成一份可以直接跟着做的清单省得回头翻安装Keil v5.11安装ST-Link驱动最后安装对应STM32芯片的Device Pack。打开或新建工程在Options for Target的Device里选择正确的STM32型号。在Debug选项卡里选择ST-Link Debugger打开Settings确认SWD模式确认能识别到SW Device。在Utilities选项卡里保持Use Debug Driver打开Settings确认Flash Download页面里的算法列表正确。勾选Program和Verify按需勾选Erase Full Chip或Erase Sectors勾选Reset and Run。编译工程确认没有语法错误。点击Download按钮烧录等待进度条完成看到校验通过提示。观察板子运行现象或者直接进入Debug模式单步验证。这个流程看起来简单初学者最容易卡在第3步识别不到SW Device或者第7步烧录报错。如果报错回看第3.1节到3.4节逐个排除。6.2 我自己的常用配置模板如果你不知道某个选项该怎么设可以直接照抄我常用的这套配置调试器ST-Link V2SWD速度1MHz杜邦线场景或4MHz短线焊接场景擦除方式调试阶段用Erase Sectors交付测试用Erase Full Chip烧录后动作勾选Reset and Run烧完直接跑编译输出勾选Create HEX File方便以后用外部工具烧录芯片Pack版本选择与当前Keil版本兼容的版本不盲目追新这套配置我在F103、F407、F030上都跑过稳定可靠可以作为你的基线配置。6.3 那些不值得折腾的烧录问题最后想说一个经历烧录问题有时不一定要死磕有些问题的性价比太低不值得花太多时间。比如烧录速度慢那么一两秒这类问题忍一忍就行再比如ST-Link硬件本身残次导致每次需要重插USB才能识别这种情况下直接换一块新的ST-Link不要在一个二十几块的硬件上浪费半天。我遇到过最耗时的烧录问题是一次芯片型号选错。当时要在STM32F103C8T6工程里烧录一个F103RCT6的板子我忘了修改芯片型号点击Download后Keil一直提示Flash算法不对我花了很久去排查明明没问题的硬件连接最后才发现是Device里选成了C8T6算法列表里是64KB的Flash算法而实际芯片是256KB匹配不上。换回正确的芯片型号后一次通过。这种时候仔细核对工程设置比反复插拔线更有效。6.4 继续深入的几个方向烧录程序是嵌入式开发的一个基础环节如果这篇文章帮你把Keil烧录搞定了后面可以考虑更深入的问题一是Bootloader的设计用串口或USB实现IAP升级这样以后就不用每次都接调试器烧录二是离线烧录器的使用用脱机编程器从SD卡或U盘里读出固件批量烧录到裸板上三是加密固件的保护方案STM32的读保护、加密算法、安全启动怎么和烧录流程结合。这些都是单片机开发绕不开的话题也都是在“烧录成功”这个起点上延展出去的。我个人的建议是先别急着追新工具把Keil这个老牌环境的烧录流程彻底吃透其他工具用起来也会顺手很多。
返回列表