你是不是也经历过这种场景:手里捏着一片STM32,好不容易焊接好板子,把ST-Link插上去,点了几下下载按钮,程序就跑起来了。你觉得这事挺简单,直到有一天同事问你“ISP和ICP到底啥区别”,你打开百度,搜出几百个帖子,每个说法都有点绕,看完更晕了。再往后做OTA升级,又冒出个IAP,你才知道原来“烧录”这件事,水比你想的深。
芯片烧录,本质上就是把编译好的固件写入芯片的存储介质里,让CPU上电后能按你的逻辑跑。但同样是“写固件”,实现路径完全不同:ISP是系统内编程,ICP是在线电路编程,IAP是在应用编程。这三个缩写看起来差不多,背后的机制、工具、适用场景差着十万八千里。这篇就用工程师平时的思路,把ISP/ICP/IAP从头到尾捋一遍,顺便把大家常搜的STC ISP下载、STM32/GD32的IAP升级、以太网OTA、FPGA配置这类延伸问题也串起来讲清楚,新手看完心里能有个完整地图。
1. 先搞清楚烧录到底在干什么
1.1 一块芯片里值得“烧”的东西
芯片烧录的对象,绝大多数是Flash。我们写的C代码编译之后变成bin或hex文件,里面包含的是机器指令和固定数据,这些内容需要存放在非易失介质里,掉电不能丢。MCU内部最常见的存储介质就是Flash,有的还有EEPROM、OTP区域、选项字节或者fuse。
Flash这个东西,你可以理解成一块可反复擦写的黑板,但它和普通RAM不一样的地方在于:写之前必须先擦除,而且擦除的最小单位通常是一个扇区或一个块,不是按字节来的。比如STM32F1的Flash,按页管理,一页1KB或者2KB;而GD32F103的扇区结构跟F1基本兼容,但不同型号会有差异。这就导致“烧录”不是简单把文件拷进去,而是一个“擦除-写入-校验”的完整流程。
很多人问:我下载程序的时候,编译器不是已经生成了hex吗,为什么点下载还要那么久?就是因为工具链要先把目标区域擦干净,再逐字节写入,最后还要读回校验一遍。校验失败会直接报错,这也是为什么有时候烧录中途断电,芯片里会留下一半新程序一半旧程序的残局。
1.2 Flash为什么不能随手写
CPU执行程序时,指令是从Flash地址里取出来的。如果Flash里的内容有问题,轻则死机,重则直接锁死芯片。更麻烦的是,Flash的写入要求电压、时序都有严格规定,不可能像操作SRAM变量那样直接赋值。
我们平时写代码时定义一个const数组,编译器会把它放到Flash区,但这只是在“编译期规划地址”,真正把内容写进Flash的,还是烧录器或IAP程序中的Flash编程驱动。这里有个关键点:芯片自己执行程序时,能不能写自己的Flash?答案是可以,但需要先把要执行的代码放在RAM里,或者让Flash控制器按特定时序操作,否则会出现“边读边写”的冲突。这个限制恰恰是理解IAP的基础。
另一个容易忽视的细节是:Flash的寿命和写入粒度。普通嵌入式Flash的擦写次数通常在1万到10万次之间,写的时候如果没做好磨损均衡,同一个扇区反复擦写,用不了多久就会坏。早期做产品迭代时,我图省事每次OTA都把整个App区擦一遍,后来出货量大了,才发现Flash寿命问题真的会找上门。
1.3 烧录、下载、编程有什么区别
这三个词在日常工作中经常混着用,但严格来说有点差别:
- “编程”(Programming)是最正式的叫法,芯片手册里常说“Flash Programming”,指的是一整套把数据写入非易失存储器的操作。
- “下载”(Download)源自仿真器时代,更强调把程序装载到芯片的RAM或Flash中运行。
- “烧录”(Burning)最早来自PROM时代,因为老式存储器烧断熔丝的行为确实像“烧”,后来沿用下来,现在已经成了行业黑话。
工程师之间沟通时,说“烧一下”没人会误解。但如果你跟硬件同事讨论“用ICP烧录选项字节”,最好知道这里的“烧录”指的是通过调试接口去改芯片的配置区,而不是普通程序下载。
2. ISP:系统内编程,芯片焊在板子上也能烧
2.1 ISP的原理和“出厂Bootloader”
ISP全称是In-System Programming,翻译过来是“在系统编程”。最直观的理解是:芯片已经焊在PCB上了,不用拆下来,通过芯片预留的接口和协议就能烧录固件。
芯片厂商会在出厂时往芯片内部写一段固定的引导代码,这段代码叫Bootloader(引导加载程序),它会监听某个外设接口,比如UART、SPI、I2C或USB。当芯片进入ISP模式后,CPU其实在运行Bootloader里的程序,而不是你的应用程序。Bootloader接收来自上位机的数据,再调用Flash驱动把数据写入指定区域。
以STM32为例,芯片出厂时System Memory(系统存储器)里有一段ROM Bootloader,支持USART、CAN、USB、I2C、SPI等多种接口下载。要让STM32进入ISP模式,通常要把BOOT0引脚拉高,BOOT1拉低,然后复位,芯片就会从System Memory启动。这时候用串口连接芯片的USART1/2,配合ST官方的Flash Loader Demonstrator或STM32CubeProgrammer,就能在没有调试器的情况下烧录固件。
很多人搜“STM32 ISP”,其实指的是这种串口下载方式。它的最大好处是:不需要额外买昂贵的调试器,哪怕芯片完全没有程序,也能活着进Bootloader。对于小批量样片烧录、生产现场应急更新,特别实用。
2.2 串口ISP实战:以STM32和STC为例
实操一下STM32的串口ISP。假设手里有块F103C8T6核心板,USB转串口模块一个,接线方式是:
- MCU的USART1_TX(PA9)接USB转串口的RX
- MCU的USART1_RX(PA10)接USB转串口的TX
- 共地
- BOOT0跳线接3.3V,BOOT1接GND
- 上电或按复位键
打开STM32CubeProgrammer,选UART,设置波特率,常见的有115200或460800。连接后芯片会响应,然后加载hex文件,点下载。下载完成后把BOOT0跳回GND,复位就能运行你自己的程序了。
这个过程看着简单,坑也不少。第一个坑是接线时TX/RX交叉,很多人接反了导致连不上;第二个坑是如果芯片的供电不稳定,串口握手会超时;第三个坑是BOOT0的电容或上拉电阻,有些板子上的BOOT0经RC电路连到3.3V,复位后要等电容充放电才能稳定进入ISP,导致每次下载都要手动按复位。
再说一个网上经常搜到的“STC ISP去弹窗”。STC单片机的下载工具ISP软件,在下载时会弹窗提示,很多人以为是软件绑架。其实本质是STC的下载协议里包含了对芯片型号识别、时钟频率校准、选项位设置的交互过程,软件需要在下载前后反复读取芯片状态。用串口助手直接干这件事干不了,因为STC的ISP协议是完全自定义的。很多老工程师的习惯是装一个稳定版本的STC-ISP,下载时把波特率调到9600或更低,能大幅减少握手失败的概率。
2.3 ISP的边界:适用场景和几个坑
ISP最大的优势是设备不需要专门调试器,只要有通信接口和一个Bootloader就能烧。但它的劣势也很明显:
- 速度慢。串口ISP通常最高到几百kbps甚至几Mbps,跟SWD的MHz级速率没法比。大固件下,你会明显感觉“等待时间变长”了。
- 不能调试。ISP只能烧录,不能用断点、单步、看变量。
- 需要进入模式。PCBA生产时,让产线工人手动拨BOOT0,不仅慢,而且容易忘记拨回。
所以ISP在实际产品里的定位,更多是“出厂引导”和“应急恢复”。真正日常开发和调试,主力还是ICP。
3. ICP:在线调试编程,工程师手里那把刀
3.1 JTAG与SWD,两条腿走路
ICP全称是In-Circuit Programming,对应“在线电路编程”。现在芯片上最常见的ICP通道就是JTAG和SWD。JTAG是个老协议,全称Joint Test Action Group,最早是为了PCB板级测试设计的,标准IEEE 1149.1,后来被拿来兼做芯片调试接口。SWD是ARM后来提出的串行调试接口,全称Serial Wire Debug,引脚更少,速度也不差。
JTAG在Cortex-M芯片上一般用的是SWJ-DP,默认5根线:TMS、TCK、TDI、TDO、nRST或nTRST。SWD则把数据简化为SWDIO和SWCLK两条,外加一个复位可选。SWD最大的好处是节省IO,很多小封装芯片只有SWD两线,照样能烧录和调试。我做过一个TSSOP20的小板子,为了省3个引脚,直接把JTAG砍掉,只留SWD,下载和在线调试完全不受影响。
很多开发板上的烧录接口,其实就是把SWD的四根线(SWDIO、SWCLK、GND、3.3V)排成一排,这就是大家常说的“SWD口”。所以看到“4针烧录座”,别觉得奇怪。
3.2 常用调试器怎么选:J-Link、ST-Link、DAP-Link
ICP烧录离不开调试器,市面上最常见的三类:
- ST-Link:ST原厂出品,用于STM32/STM8,最新版V3支持虚拟串口和USB转串口,价格便宜,兼容性好。缺点是对非ST芯片支持差。
- J-Link:SEGGER出的,兼容性最强,支持ARM各个内核,还有强大的软件生态(J-Flash、RTT等)。正版贵,但市面上几十块的“兼容版”在业余和教学场景也大量存在。需要注意的是,如果J-Link固件版本太老,可能会识别不了新内核,所以用J-Link时记得及时更新软件。
- DAP-Link:ARM官方的开源方案,用CMSIS-DAP协议,可以自己画板子或买现成的。需要跑高速下载时,兼容版DAP-Link往往受限于USB实现,速度不如ST-Link和J-Link稳定,但对于日常学习调试完全够用。
选型建议很简单:搞STM32就ST-Link;做多平台项目、涉及NXP/GD/AT32等多种芯片,J-Link是最稳的选择;如果追求便宜且想折腾,DAP-Link加一个国外开源固件,下载速度也还行。
3.3 不只是烧录:读保护与选项字节
ICP和ISP另一个大区别是:ICP能访问芯片的调试接口,也就意味着能控制调试功能。于是就有了安全话题。Cortex-M内核芯片大多提供读保护(Read Protection)机制,比如STM32的RDP分Level 0、Level 1、Level 2。
Level 0是不保护,调试器随便读Flash;Level 1是启用保护,调试器的Flash读取被禁止,但可以通过全片擦除回到Level 0;Level 2是永久保护,不可降级,芯片内部调试口直接被禁用,相当于把联调功能焊死。做量产产品时,一般会设Level 1,防止固件被外界直接读出。设置读保护是通过ICP往选项字节区写入配置实现的,这操作经常和“烧录程序”一起做。
这里有个新手容易踩的坑:如果你开了Level 1读保护,自己下次想用调试器下载程序,会报“not permitted”之类的错。解决方法是先做全片擦除,再重新下载。代价是芯片里所有数据都没了,出厂校准数据如果存在Flash里也会丢。所以做保护之前,先把该读出来的数据备份好。
3.4 ICP量产:从手工下载到脱机编程器
ICP做产品量产时,最常见的做法是“一台电脑+一个调试器+一块待烧板子”。如果产品量大,电脑来回插拔效率低,就需要脱机烧录器。
脱机烧录器本质是一个内置存储的编程器,先把固件文件导入它内部,然后通过探针或者夹具接触目标板,一键烧录。像STM32可以通过SWD接口用脱机编程器烧写,生产线上会有专门的烧录夹具,QC人员只需要把板子放上,按下按钮,读灯亮即可。脱机烧录器在批量生产时能极大提高效率,同时减少电脑USB口被反复插拔导致的接触不良问题。
但脱机烧录器也有成本:好一点的设备几百到几千块,而且固件更新时要把新文件先灌进编程器,这一步流程不能忘。很多工厂的实际做法是:产线入库前用脱机烧录器烧第一批,等量产稳定后统一升级烧录器的固件版本,防止新旧固件混用。
4. IAP:程序里长出自己的升级能力
4.1 BootLoader + App 的架构思路
IAP全称是In-Application Programming,意思是“在应用编程”。它的核心思想是:芯片运行着你的应用程序,应用程序自己就能把新的固件写入Flash,实现自我升级。
要做到这一点,需要把芯片Flash分区。典型布局是:BootLoader区(如0x08000000,大小16KB或32KB)+ App区(如0x08004000,剩余空间)+ 参数/标志区。上电后CPU先跑BootLoader,BootLoader判断是否需要升级。需要,就走升级流程;不需要,就跳转到App区执行你的业务逻辑。
这个架构最玄妙的地方在于:BootLoader和App是两个独立的程序,它们不能同时运行,而且BootLoader代码里必须包含对Flash的操作驱动、通信协议(比如串口/以太网/USB)、以及跳转逻辑。App则需要在编译时修改链接地址,让程序知道自己跑在哪个位置。
有人问:BootLoader不也是程序吗?它怎么不去运行自己的Flash驱动?其实BootLoader自己就在Flash里跑,它执行时读自己的代码没问题,但当它去写App区的Flash时,写操作本身不涉及自己所在区域的擦写,所以不会冲突。如果BootLoader试图擦除自己所在的扇区,那就会把自己搞死,所以BootLoader必须保护自己的空间。
4.2 最小IAP怎么落地:从跳转到刷写
以STM32为例,一个最小IAP系统大概分三步。
第一步,规划地址。BootLoader放0x08000000,App从0x08008000开始(假设BootLoader占用32KB)。在App工程里,需要修改链接脚本或者IDE里的Flash起始地址为0x08008000,同时把中断向量表重定向到App区。在Cortex-M上,操作方法是把VTOR寄存器指向App的基地址:
SCB->VTOR = 0x08008000;如果不做这一步,App里的中断来了之后,CPU还是去0x08000000找向量表,结果执行的是BootLoader的中断处理,系统会乱套。
第二步,BootLoader跳转。跳转的本质是把栈指针和复位向量设置到App区:
typedef void (*pFunction)(void); uint32_t AppAddress = 0x08008000; // 检查栈顶地址是否合法(RAM区间) if (((*(volatile uint32_t *)AppAddress) & 0x2FFE0000) == 0x20000000) { // 把App的初始SP赋给MSP __set_MSP(*(volatile uint32_t *)AppAddress); // 取出App复位向量,也就是App第一条指令的地址 pFunction jump = (pFunction)(*(volatile uint32_t *)(AppAddress + 4)); // 跳过去执行 jump(); }跳转前记得关掉BootLoader里打开的中断、关闭SysTick,否则跳进App后可能会产生异常。这个细节特别坑,调试时你会发现明明跳转地址对了,程序却突然进HardFault。
第三步,在App中接收固件。最常见是串口协议:App收到“升级请求”后,进入BootLoader(可以置标志位后复位,也可以直接在App里调用跳转)。BootLoader复位后检查标志位,如果标志有效,就开始接收新固件,写入App区。写入时可以用STM32的Flash库或HAL:
// 擦除目标扇区 FLASH_EraseInitTypeDef erase = {0}; erase.TypeErase = FLASH_TYPEERASE_PAGES; erase.PageAddress = 0x08008000; erase.NbPages = 128; HAL_FLASHEx_Erase(&erase, &page_error); // 按半字写入 HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr, data);写完以后,校验一下整个App区的CRC32或MD5,没问题再置“升级完成”标志,复位跳转。
4.3 升级失败和设计回退
IAP最有价值的地方不是“能升级”,而是“升级失败了怎么办”。试想一下:升级过程中突然断电,App区被擦了一半,系统下次上电连你自己的业务程序都起不来,那就成了砖。
所以成熟的IAP方案都有备份机制。常见的做法是设计两个App槽位:
- App A(当前运行)
- App B(待写入)
BootLoader每次升级时,先把新固件写入App B,写完校验通过后,把“启动地址”标志指向B,再复位。如果校验失败或者运行后看门狗超时,BootLoader把启动地址改回App A,实现自动回滚。这种方式占Flash空间大,但能把“变砖”的风险降到最低。
还有更轻量的方案:不搞双槽,但保留一份出厂固件,或者只在App区加一个“热回滚标记”,每次升级前先把当前固件备份到另一块区域。具体取舍要看产品对容错的要求:消费类电子产品断电概率不高,但医疗设备、工业控制器对升级可靠性极其敏感,双槽几乎是标配。
看门狗在IAP里很重要。BootLoader升级时,通常要给外部或内部看门狗喂狗,但喂狗逻辑要控制好:如果升级流程卡住了,喂狗反而会掩盖问题。我更习惯的做法是:升级过程里设一个“超时看门狗”,超过比如30秒没有收到完整固件,就直接复位放弃本次升级,回到正常App。这个逻辑看似简单,但真到了现场调试升级失败时,能省很多排查时间。
4.4 进阶:以太网OTA与特殊芯片方案
IAP里“升级包从哪里来”是个大话题。除了串口,最常见的是以太网OTA。
实现以太网IAP,主要有两种路径:一种是在App里把固件下载到外部Flash或RAM缓冲,再写到自己Flash;另一种是BootLoader自带网卡驱动,直接通过TFTP/HTTP/FTP协议下载固件。
很多人搜“ETH IAP怎么实现”,其实问的就是BootLoader里怎么写网络协议栈。在STM32或GD32这类MCU上,要让BootLoader跑以太网,就得在BootLoader里集成以太网驱动、轻量级TCP/IP协议栈(比如lwIP),还要处理DHCP或静态IP。这个方案功能强,但占资源也厉害:一个跑以太网的BootLoader可能占几十KB Flash,对芯片容量本身有要求。
一个比较偏门但实际常用的套路是:App跑完整网络协议栈,把升级固件先收到外部SPI Flash里,同时做个标记;复位后BootLoader发现标记,直接从SPI Flash把固件搬到内部Flash,完成升级。这样BootLoader不需要网络功能,只需要SPI Flash的驱动,代码量小很多。我做过一个路灯控制器,MCU内部Flash只有256KB,又必须支持远程升级,就是靠外部SPI Flash做缓存区,BootLoader只有8KB,非常省。
搜“GD32F103 IAP升级”的人,多半是被GD和STM32的兼容性给绕进去了。GD32F103整体引脚跟STM32F103兼容,Flash操作寄存器也大体相似,但GD的Flash控制器有自己的特点,比如读等待周期要求不同、扇区大小有变化。如果你在GD上直接用STM32的HAL库做IAP,很可能会擦除出错或烧写失败。最稳妥的办法是:使用GD官方提供的固件库,或者对照GD32数据手册,把Flash操作部分换成GD的API。还有一种野路子是直接用寄存器操作绕开库函数,但你自己得心里有数,别抄错地址。
还有一个经常被点名的问题是STM32H750VBT6的IAP。这颗芯片非常特殊,标称Flash只有128KB,但RAM很大。跑大型应用时,很多开发者会外挂QSPI Flash存代码,再通过内存映射XIP方式执行,这时候IAP就不是往内部Flash写了,而是要往外部Flash写,甚至要考虑在QSPI Flash里做双Bank。你可以把它理解成“换个烧录对象”,原理还是擦除-写入-校验,但驱动和地址映射上会复杂很多。
至于FPGA ISP或“FPGA在线配置”,其实是另一套逻辑。FPGA没有传统意义上执行程序的Flash,它的程序叫比特流(bitstream),一般存在外部SPI Flash或内部配置存储器里,上电时由FPGA自己加载。更新固件通常是通过JTAG配置或者写外部Flash,和MCU的ISP/ICP/IAP不是同一套东西,只能说“叫法类似,机制完全不同”。很多新手混在一起,学到后面才发现跑偏了。
5. ISP / ICP / IAP 怎么选:一张表看清项目决策
5.1 核心对比
说了这么多,直接上对比表,方便收藏。
| 对比项 | ISP | ICP | IAP |
|---|---|---|---|
| 中文名 | 在系统编程 | 在线电路编程 | 在应用编程 |
| 主要通道 | 串口/SPI/I2C/USB等 | JTAG/SWD调试口 | 自定通信协议(串口/网口/USB等) |
| 是否需要额外硬件 | 通常需要USB转串口或对应接口 | 需要调试器(ST-Link/J-Link) | 无需调试器,使用板载通信接口 |
| 进入方式 | 芯片Bootloader+引脚状态/特定指令 | 调试器直接接管CPU | 复位后执行BootLoader,根据标志跳转 |
| 能否调试 | 不能 | 能(断点/单步/查看变量) | 不能(除非BootLoader内部留调试口,实际很少) |
| 速度 | 中低,受串口等外设限制 | 快,MHz级 | 取决于通信协议,串口OTA相对慢,网络OTA较快 |
| 典型场景 | 出厂烧录、串口应急下载 | 日常开发调试、产线脱机烧录 | 产品远程升级、OTA |
这张表里最容易被误解的是ISP和ICP。很多人以为ISP“不用外部编程器”就等于“不用硬件”,其实不对,ISP同样需要一根线连到上位机,只是对调试器没要求。ICP的优势是可以同时调试,这让它在开发阶段几乎是标配。
5.2 项目阶段选型经验
从项目全生命周期看,三种烧录方式的角色很清晰:
- 原型开发期:主力用ICP,因为要频繁改代码、查变量、看波形。ST-Link或J-Link插着,IDE里一键下载调试,效率最高。
- 小批量试产:可以继续用ICP+脱机烧录器,但要在烧录流程里固化“擦除、写Flash、写选项字节、校验”的完整动作。建议先把芯片的读保护等级定好,否则后期想加密,还得再返工。
- 大批量量产:靠手工插调试器不现实,上脱机编程器或在线测试夹具(ICT)同步烧录,配套防错托盘,保证每一片都烧对烧全。
- 产品交付后:IAP是必须设计的。哪怕第一版固件不准备OTA,也建议在设计阶段就把BootLoader+App的结构留好。不然产品已经卖出去了,想加远程升级,得先飞线烧BootLoader,这个成本要命。
我个人的经验是:哪怕一款产品永远不出厂升级,也把BootLoader放进去,占8KB或16KB不算多,但这是给未来留的“逃生通道”。真遇到线上故障,能远程刷固件救回设备,比派人背着烧录器出差强太多了。
6. 新手常见问题排查实录
6.1 烧录失败排查速查表
直接把这些年遇到的常见问题整理在这里,按症状排查。
| 症状 | 可能原因 | 处理办法 |
|---|---|---|
| 使用SWD连接总是报“No target connected” | 板子没供电、SWDIO/SWCLK接反、芯片被读保护锁死、复位引脚被拉低 | 先量供电,再查线序,尝试按住复位的同时点击连接,必要时全片擦除一次 |
| 串口ISP连不上,握手超时 | TX/RX交叉错误、波特率不对、BOOT0状态不对、共地没有 | 重新确认交叉接线,换低波特率(9600),拨BOOT0后重新上电复位 |
| IAP跳转后程序跑飞/进HardFault | 中断向量表没重定向、跳转前中断未关闭、栈指针检查不对 | 在入口关闭中断,检查VTOR设置,确认App工程链接地址正确 |
| 烧录提示“RDP not permitted” | 芯片开了读保护,调试器无法再次访问 | 尝试全片擦除或使用调试器执行解除保护(Unsecure),注意会清空数据 |
| 下载后程序不运行 | 复位条件不对、BOOT引脚设置留在ISP模式、电源不稳导致Flash校验失败 | 确认BOOT0为低电平,稳压器输出正常,检查“下载后复位运行”选项 |
| GD32使用STM32库烧写失败 | Flash操作不兼容 | 换用GD官方库,或查看GD32数据手册,慎重对待Flash等待周期和扇区划分 |
| 以太网OTA升级到一半断连,设备变砖 | 没有双槽机制,固件校验不完整 | 增加双BANK/双槽设计,关闭看门狗的超时时间,采用块校验和完整包CRC,失败自动回滚 |
这里特别提醒一句:遇到“连不上”的问题,第一反应不要怀疑芯片坏了,先量电源、量地、量线序。我调试经验里,至少有一半“芯片没办法连接”的故障,最后查出来是杜邦线松动或地没共好。第二反应是“芯片是不是被保护了”,尤其是二手芯片或别人用过的板子,很有可能是开了读保护。从便宜怀疑到贵,能省很多时间。
6.2 现场调试技巧和工具细节
调试烧录问题,手腕要活,分享几个我自己一直在用的小招数:
- 加串口日志。ISP连接不上时,可以用示波器或逻辑分析仪看TX/RX线上有没有数据波形。如果在发数据,但握手失败,多半是协议或波特率问题;如果连波形都没有,说明MCU根本没进Bootloader,问题大概率在BOOT引脚或启动模式。
- 按住复位连接。用SWD连接有些时候因为芯片跑飞或死机导致调试口失效,按住复位键,在IDE点击连接的同时瞬间松开,能提高连接成功率。原理是让调试器抓住了CPU复位后未运行的一条腿,趁虚而入。
- 下载后自动运行。STM32CubeProgrammer里有个选项“Reset after programming”和“Run after programming”,勾选后能省掉手动按复位的操作。产线烧录时,这个选项能提升幸福感。
- 用软件复位代替拨码开关。产品出厂后没法拨BOOT0,如果你需要远程让芯片进Bootloader,可以在App里通过“设置标志位+软件复位”的方式进入。这个标志位可以放在备份寄存器里,也可以在RAM里,重要的是复位后不能被BootLoader立刻清掉。
6.3 排查的思维顺序
最后聊一下排查烧录问题的思维顺序,这是书本上不讲的。
第一步,从整体链路看。完整烧录链路是“上位机软件-调试器/串口线-芯片引脚-芯片内部Bootloader/调试口”,任何一个环节断了都白搭。先确认每个环节的硬件连接,再怀疑软件配置。
第二步,从“最小可复现单元”排查。比如串口ISP连不上,你手头有没有一个确认能用的模块,先确认USB转串口模块本身能发数据。或者换一块确定能烧写的板子,确认调试器没坏。不要一上来就怀疑芯片固件库或IDE设置。
第三步,记录错误信息。很多烧录工具会给出错误码和说明,比如STM32CubeProgrammer会告诉你“No STM32 target found”或“Error: Data length exceeds target memory size”。这些信息不要略过,搜索引擎一查,基本能定位。
第四步,针对IAP类疑难杂症,要学会用“串口打印BootLoader状态”。BootLoader里加几行调试打印,把升级流程的每步状态打出来,包括“收到包头、正在擦除、写入到哪个地址、校验结果”。开发时这会多耗点时间,但产品上线后排查问题会轻松很多。
这篇文章写到这里,想说的核心其实就一句:ISP/ICP/IAP不是三个互相孤立的技术名词,而是芯片开发从原型到量产再到维护的三种“给药方式”。开发时靠ICP吃饭,量产时靠ISP或脱机烧录提效,产品上线后靠IAP续命,三者配合,才是一个完整的固件生命周期管理方案。
如果你正准备给自己的板子设计IAP,我的建议是:第一版不要贪功能,先把“串口升级+跳转+失败回退”跑通,再去折腾以太网OTA、加密签名、双槽热备份。一步一步来,比什么都快。