有朋友拿了一块带摄像头的开发板问我:你们搞嵌入式的人天天嘴里念叨 ISP,是不是就是芯片烧录里那个 ISP?我说不完全是——芯片烧录里的 ISP 是 In-System Programming,而摄像头那边说的 ISP 是 Image Signal Processor,图像信号处理器。类似的误会还有一大串:做点云处理的听到 ICP,第一反应是迭代最近点配准;做电商听到 IAP,想到的是 App 内购买。但在嵌入式烧录这个语境里,ISP、ICP、IAP 恰好是三种完全不同的程序写入方式。
这个缩写撞车的现场,反而很适合作为理解芯片烧录的切入点。因为很多人第一次接触“烧录”这个概念,就是从这三个缩写开始的。你会看到下载程序叫“ISP 下载”,调试器写 Flash 叫“ICP”,产品要支持 OTA 升级叫“IAP”,每个字都认识,但搞不清它们到底差在哪。今天这篇就把三者的原理、适用场景、实际操作和常见坑一次讲透,争取让没接触过单片机的新手也能在读完以后,知道手里那块芯片是怎么被“写进”程序的。
1. 先搞清楚“烧录”烧的是什么,以及为什么这组缩写总是撞车
烧录这个词听起来有点古老,像是什么烧录机、烧熔丝的动作,事实上它确实是从半导体工艺早期留下来的叫法。最早的 PROM 芯片出厂时每个存储单元是通的或者断的,要用超过正常工作电压的“编程电压”把熔丝烧断来记录 0/1,所以真的是在“烧”。到了 EPROM 时代改成了紫外光擦除、高压写入,再往后 Flash 时代变成了纯电气擦写,但“烧录”这个叫法留了下来。今天说的芯片烧录,本质就是把编译好的固件(bin/hex 文件)写入芯片的非易失性存储介质,一般是内部 Flash,让它掉电不丢、上电能跑。
烧录过程听起来简单——就是拷文件嘛——但芯片不是 U 盘,它没有一个对外的通用文件系统接口。CPU 内核访问 Flash 通常是通过内部总线,而 Flash 的擦写又有一套时序要求:要先发命令、解锁寄存器、按扇区擦除、再按字或页写入、最后回读校验。这一整套动作,必须由某个“执行者”来发起。也就是说,芯片烧录方案的本质区别不在烧录动作本身,而在“谁来替你执行擦写算法”。按这个标准来看,ISP、ICP、IAP 分得非常清楚,我们后面会逐一展开。
先看看缩写撞车有多严重,下面这张表是我在实际工作和逛社区时积累下来的高频歧义场景:
| 缩写 | 本领域含义 | 其他常见含义 | 容易混淆的语境 |
|---|---|---|---|
| ISP | In-System Programming,在系统编程 | Image Signal Processor,图像信号处理器;Internet Service Provider,网络服务商 | 摄像头 ISP pipeline、富瀚 ISP 芯片、ISP 图像处理 |
| ICP | In-Circuit Programming,在电路编程 | Iterative Closest Point,迭代最近点配准 | 点云配准、三维视觉里的 ICP 配准 |
| IAP | In-Application Programming,在应用编程 | In-App Purchase,应用内购买 | 手机 App 内购、游戏充值 |
你看,同样是 ISP,在摄像头的语境下它是一颗专门做图像信号处理的芯片或者 IP,像富瀚微电子的 ISP 方案,业内常讨论 ISP pipeline 怎么调噪点、怎么对齐 HDR;在嵌入式烧录语境下,它却是串口下载程序的一种模式。ICP 更不用说了,机械臂抓取、三维重建的工程师听到 ICP 第一反应是算法,而不是写芯片。所以如果你在网上搜“ISP 是什么”,看到一堆图像处理文章完全正常,要先把领域对齐,再往下聊。本文下面的 ISP、ICP、IAP,都特指芯片烧录范畴。
2. 所有烧录方案殊途同归:擦除、写入、校验,只是控制权在不同人手里
理解了烧录动作本身之后,再深入一层看硬件结构。任何一颗具备可编程能力的 MCU,内部都有一个Flash 控制器,CPU 可以把 Flash 当成外设来操作,通过一组寄存器发起擦除、编程、校验操作。问题在于:**芯片刚出厂的 Flash 是空的,CPU 里也还没有任何程序,这时候谁来跑 Flash 控制器代码?**这就是“先有鸡还是先有蛋”的问题。
为了回答这个问题,芯片设计者做了三套不同的入口:
- ICP:通过芯片内部硬件实现的调试接口(JTAG/SWD),由外部调试器直接接管 CPU 内核,让 CPU 暂停下来,然后把擦写 Flash 的指令一条条通过调试总线灌进去执行。相当于外部有个人拿着钥匙,把门打开,进到屋里亲手操作。
- ISP:芯片出厂时在 ROM 里固化了一段出厂引导程序,叫 BootROM。上电时如果检测到特定引脚电平组合,CPU 就会跑这段 BootROM,从串口、USB 等外设接收数据,再由 BootROM 里的代码去操作 Flash 控制器。相当于芯片自己带了个服务员,你从窗口递东西给它,它帮你放进仓库。
- IAP:芯片里已经跑着你自己的应用程序,这个程序在运行时,主动调用 Flash 控制器接口,把 Flash 里另一块区域擦掉、写上新的固件。相当于住在屋子里的人自己动手换家具。
三种方案的差异可以总结成一句大白话:**ICP 是外人直接进屋,ISP 是出厂服务员代劳,IAP 是屋里人自己动手。**而不管是哪种,最终落到 Flash 里的动作都一样,无非是三步:擦除整块/扇区、按地址写入数据、回读比对校验。在理解后面的操作细节之前,先把这三个控制权分配记牢,就不会被各种烧录名词绕晕。
另外一个需要了解的基础概念是启动模式。大多数 MCU 上电以后,CPU 会从复位向量指定的地址取第一条指令。STM32 这一类芯片有 BOOT0/BOOT1 引脚,用来决定第一条指令是从主 Flash 取、从系统存储器(存放 BootROM)取,还是从 SRAM 取。ISP 之所以能工作,就是利用这个机制强制把 CPU 引导到 BootROM 里。同理,IAP 也是利用了启动模式的切换,把原本要从主 Flash 启动的程序,改成先从 BootLoader 启动,再由 BootLoader 跳转到 App。后面逐一拆解。
3. ICP:最“硬核”的外部直写,调试和量产两开花
ICP 全称 In-Circuit Programming,中文叫在电路编程。这里的“在电路”指的是芯片已经焊到 PCB 上、供电也正常,调试器通过调试接口直接对芯片进行操作。它和“离线烧录”或“编程器烧录”是两个路子。离线烧录是把芯片拆下来放到编程器座子里写好了再贴回去,ICP 则是把调试器接到板子的调试口上完成写入。
3.1 ICP 的底层原理:调试器如何接管 CPU
大部分 MCU 内部集成了调试接口硬件,ARM Cortex-M 内核最常见的 SWD(Serial Wire Debug)两线调试,加上供电地线,实际连接只需要四根线:SWDIO、SWCLK、GND、VCC(VCC 主要是让调试器感知目标板电压)。调试器在 SWD 协议层发送指令,比如让 CPU 停在复位向量处、让调试接口读取目标板上的寄存器地址空间。因为 ARM 的调试接口可以直接访问 CPU 寄存器、系统总线、内存和外设,只要 Flash 控制器映射在总线地址空间里,调试器就能像读写内存一样去操作 Flash 擦写算法。
你可以把 SWD 想象成一根能伸进芯片内部的“数字探针”,它不光能看,还能操作。J-Link、ST-Link、DAP-Link 这些常见调试器,核心能力都差不多,差别主要在速度、支持的芯片种类和软件生态。
STM32 用 ST-Link/J-Link 烧录的典型流程是这样的:
- 接线:SWDIO、SWCLK、GND、3.3V,保证共地;
- 打开工具(STM32CubeProgrammer 或 Keil MDK 的 Flash Download),连接目标芯片;
- 工具读取芯片 ID,确认型号匹配;
- 自动擦除所需扇区(也可以只擦除要写到的区域);
- 把 hex/bin 数据按地址写入,写完后回读校验;
- 复位芯片,程序开始运行。
整个过程不需要芯片里预先有任何代码,因为调试接口是芯片的“硬件后门”,出厂就存在,烧录空片也完全没问题。这也是为什么调试器烧录是研发阶段最常用的方案——焊上去一块全新的空片,接上调试器就能烧,烧完直接打断点调试,一条龙服务。
3.2 量产场景里的 ICP:脱机烧录器和夹具
ICP 不只是研发期用。生产线上批量烧录时,常见的方案是脱机烧录器。这种设备可以先把固件下载到烧录器内部存储里,之后完全脱离 PC 运行。产线上工人把待烧录的 PCB 板放到烧录夹具上,针床压住 SWD 焊盘,按一下按钮,哔一声烧完,拿下来放下一块。脱机烧录的好处非常实在:产线不可能给每台工位配一台电脑,也不可能让工人每次烧录都去操作一堆软件菜单;脱机设备带指示灯和蜂鸣器,状态清晰,坏板能立刻报警拒绝继续烧录,稳定性和防呆能力都远高于电脑在线烧。
我见过不少小批量产品用“一拖四”甚至“一拖八”的在线烧录方案,一台电脑拖四个调试器同时烧四块板,效率翻倍但管理复杂;真正做大批量出货的工厂反而更信任脱机烧录器配防错夹具,这套组合能承载几万甚至几十万片的产能规划。
3.3 ICP 的局限和最常见的坑
ICP 并不是万能的,第一个问题是占用调试口。SWD 需要 SWDIO 和 SWCLK 两个引脚,产品上如果空间紧张、引脚复用紧张,你想省掉这个接口,就得提前想清楚后面还保不保留烧录能力。第二个问题是调试口会被锁死。很多 MCU 支持读保护(RDP),如果软件里开了最高等级读保护,调试接口对 Flash 的访问就会受限,甚至完全关闭。我一个真实踩过的坑:样机调试阶段一切正常,后来为了防抄板开启了读保护,又加了一版程序通过 IAP 升级,结果新程序有 bug 跑不起来,想用 J-Link 重新烧,调试器连接被拒,最后只能走串口 ISP 强制全片擦除才救回来。所以在量产前,一定要明确调试口的最终策略:是保留 SWD 方便返修,还是直接锁死防抄板,两者不可兼得。
另外,ICP 烧录时如果目标板供电不稳,很容易烧一半失败,校验不通过重新来往往是小事,极端情况可能把 Flash 操作时序搞乱,芯片锁死。稳妥的做法是:烧录过程中由烧录器或夹具提供稳定电源,目标板不要带大负载(比如电机、大屏背光),生产测试环境和研发台面的供电条件不一样,别省这点布局成本。
4. ISP:藏在芯片里的出厂“服务员”,串口下载的灵魂
如果说 ICP 是外部直写,那 ISP(In-System Programming,在系统编程)的最大特点就是:不需要调试器,只要芯片上电时进入了出厂 BootROM,它自己就会通过串口、USB、CAN 等接口接收固件并写进 Flash。新手的第一次单片机烧录,大概率就是从 ISP 开始的,尤其是 STC 单片机的串口下载,很多人的入门仪式就是点下载、断电、上电。
4.1 BootROM 与启动引脚:ISP 能工作的地基
每一颗支持 ISP 的 MCU,在出厂时都默默烧录了一段引导代码,一般存放在独立于用户 Flash 的 ROM 区域。这段代码外界无法改写,它的职责就是在特定启动模式下初始化时钟和外设,然后在一个固定的通信接口上监听一段固件下载协议,接收到完整数据后调用 Flash 控制器完成写入。
以 STM32 为例,BOOT0 引脚拉高、BOOT1 引脚拉低时,芯片从系统存储器启动,也就是运行出厂 BootROM。此时你通过 USART1(或 USART2/USART3,视型号而定)发命令,就能进入下载模式。下载完成后把 BOOT0 拉低、复位,芯片就从主 Flash 启动,跑你刚烧进去的程序。STC 单片机不通过引脚切换,而是靠冷启动检测——下载软件点击“下载”之后,芯片要断电再上电,BootROM 才能抢在用户程序之前接管串口。这也是“STC ISP 下载必须断电上电”这个经典操作背后的原理。网上很多人讨论 STC 下载软件的各种使用体验问题,什么弹窗、卡顿之类,这里不展开;你只要记住它的设计逻辑是:上电复位的一瞬间,BootROM 检查串口是否有合法的下载请求,有就留在下载模式,没有就跳到用户程序,这就够了。
4.2 串口下载的完整链路与自动复位电路
ISP 下载最经典的连接方式是 USB 转串口。TXD 接目标板的 RXD,RXD 接目标板的 TXD,GND 共地。手动操作时流程是:
- 确认目标板处于 ISP 模式(通过 BOOT 引脚或冷启动时序);
- 打开厂商工具,选择芯片型号、串口号、固件文件;
- 点击下载,等待数据发送完成;
- 目标板复位,从用户程序启动。
量产或开发中频繁下载时,人会烦死手动断电上电的动作,所以网上常见的自动下载电路用到了串口 DTR/RTS 信号的时序控制——上位机通过电平翻转去按复位键和拉 BOOT 引脚,实现不用手碰板子就能进入下载模式。ESP32 的经典下载电路里,EN 和 IO0 分别挂在 DTR/RTS 上,借助电容和二极管搭出时序组合,原理是一样的:用串口线的辅助信号模拟手动按键过程。
4.3 ISP 与 FPGA 的“配置”到底是不是一回事
热搜词里出现“FPGA ISP”“ISP 下载”,这里确实容易混淆。FPGA 没有 Flash 程序的概念,它靠 SRAM 里的配置数据运行逻辑,断电就丢,所以每次上电都要从外部 SPI Flash 加载配置文件。把配置文件写进 SPI Flash 这个动作,有些调试器在界面上也叫“ISP”,因为同样是通过 JTAG 或 SPI 接口在系统内写入非易失存储,原理上和 MCU 的 ISP 类似——都由一段已经存在的引导逻辑(FPGA 里的配置控制逻辑)接收外部数据,再写入 Flash。但严格来说,FPGA 的配置下载过程跟 MCU 的 ISP 在细节、协议上都不同,聊烧录时提到“FPGA ISP”通常是在讨论“怎么把 bitstream 固化到配置 Flash 里”。理解这个区别就可以。
4.4 ISP 的边界:BootROM 也不是什么都能干
ISP 最吸引人的地方是只需留一组串口或 USB 引脚,不需要专用调试器,对低成本产品非常友好。但它的限制也很明显:
| ISP 的限制 | 具体表现 |
|---|---|
| 速度慢 | 串口波特率受限于 BootROM 实现,常见 115200 或 460800,相比 SWD 的 MHz 级别慢不少 |
| 烧录范围受限 | BootROM 一般只开放用户程序区,OTP 区、选项字节等特殊区域的读写权限很严格 |
| 协议固定 | 厂商 BootROM 支持的命令集是出厂写死的,无法注入自定义烧录逻辑 |
| 占用启动引脚 | BOOT 引脚、冷启动时序要求必须保留到 PCB 设计中 |
另外,ISP 不等于“任何串口都能下载”。不同厂商对 ISP 通道的选择差异很大,比如 STM32 早期主要通过 USART1,有些国产芯片用 UART0、CAN 或者 USB。GD32、HC32L136 这类国产 MCU 的 ISP 通常会兼容 ST 的启动流程,但要仔细看数据手册里“Boot configuration”和“System Memory Boot Mode”这个章节,不要把引脚接错,芯片型号选择错,工具连不上时,先检查是不是 Boot 引脚电平不对,再检查串口交叉和波特率。
5. IAP:让应用自己更新自己,OTA 升级的地基
IAP(In-Application Programming)我认为是三者里最值得花时间理解的,因为它牵扯到嵌入式体系结构里最核心的设计——设备如何安全地升级自己。热搜里“stm32h750vbt6 iap”“gd32f103 iap升级”出现频率很高,说明这已经是很多产品落地的刚需,不过入门时被跳转、分区、向量表偏移这些概念劝退的也大有人在。这部分我尽量说得细。
5.1 BootLoader + App 双区架构
IAP 最常见的落地形态是芯片的 Flash 被划分为两个区域:一块放 BootLoader,一块放 App。上电时,CPU 先从 BootLoader 启动(因为复位向量指向 Flash 起始地址,而 BootLoader 通常放在这里)。BootLoader 做一件简单的事:判断是否有升级请求(比如串口收到升级命令、外部按键按下、某 GPIO 电平变化),如果有,就从通信接口接收新固件写入 App 区;如果没有,就跳转到 App 区执行。
这里最关键的是“跳转”这个动作。Cortex-M 内核的跳转并不只是改 PC 指针那么粗暴,你必须先做四件事:
- 关闭全局中断(避免中断嵌套状态下跳到 App 后从旧的向量表取中断入口);
- 从 App 区域起始地址取出新的栈顶地址(第一个 32 位字);
- 从 App 区域起始地址 + 4 处取出新的复位向量地址;
- 把栈顶地址写入 MSP,把复位向量地址写入 PC 并跳转。
用 C 代码写出来大概是:
typedef void (*pFunction)(void); void jump_to_app(uint32_t app_addr) { uint32_t stack_addr = *(__IO uint32_t *)app_addr; uint32_t reset_vector = *(__IO uint32_t *)(app_addr + 4); pFunction app_entry; __disable_irq(); // 先全局关中断 SCB->VTOR = app_addr; // 偏移向量表 __set_MSP(stack_addr); // 然后设栈指针 app_entry = (pFunction)reset_vector; app_entry(); // 跳转 }看到没,核心是向量表的理解和中断的优先级。很多人 App 跳过去了但一进中断就死机,多半就是 VTOR 没设置或没关中断。
5.2 向量表偏移:App 中断能正常工作的关键
向量表是中断和异常入口地址的清单,Cortex-M 上电时默认从 Flash 起始地址读取。BootLoader 放在 Flash 起始地址,向量表自然在起始地址;而 App 偏移到了后面的地址,它自己的向量表也跟着偏移了。这时候必须把 VTOR(Vector Table Offset Register)设置为 App 的起始地址,CPU 才知道遇到中断该去哪里找入口。
我在用 GD32F103 做 IAP 的时候就踩过一次:BootLoader 跳转 App 后主流程能跑,LED 也闪,但一串口中断就 HardFault。查了半天,发现固件里用的是标准库,标准库的系统初始化里会设置 VTOR,但设置的前提是工程宏定义里的 VECT_TAB_OFFSET 匹配分区地址。如果工程创建时忘了改这个宏,VTOR 没偏,中断进来还是跳到 Flash 起始处的向量表,而那里全是 BootLoader 的入口,自然死机。**STM32H750VBT6 这类 Cortex-M7 芯片做 IAP 时同样绕不开 VTOR,只是 H750 的 Flash 比较小(片内用户 Flash 只有 128KB),分区规划尤其吃紧,很多人会把 App 设计成从外挂 QSPI Flash 启动或只保留 Boot + 一个精简 App,做增量升级。**分区之前一定把可用 Flash 大小、擦除粒度、App 大小余量算清楚,别等产品上线后才发现 App 放不下。
5.3 BootLoader 里定义的变量,跳转后到底怎样
这是热搜里一个很有意思的问题:“iap boot里面定义的变量复位后会怎样”。分两种情况说清楚:
**第一种:跳转方式是长跳转(函数指针直接跳,不经过系统复位)。**这种情况下,BootLoader 里的全局变量物理上还留在 SRAM 里,数值没有被主动清掉。但你的 App 并不能合法地读它,因为两个工程的编译器对地址空间的规划是独立的,Boot 的全局变量地址和 App 的全局变量地址很可能重叠,或者 App 根本不知道那个地址该当什么类型用。更麻烦的是,App 启动代码(启动汇编里的 Reset_Handler)会执行 .data 段拷贝和 .bss 段清零,如果你在主程序里依赖一个“Boot 传过来的变量”,它的地址属于 App 自己管理,值已经被初始化逻辑覆盖了,完全不可控。
**第二种:跳转方式是软复位(复位后 BootLoader 再判断跳转)。**那变量重启后当然被清零了,任何数据想传到 App,只能靠固定地址的 RAM 协议块、Flash 里的标志位或寄存器。所以正确做法是:需要跨 Boot/App 传递的信息,要么放在固定绝对地址(比如在链接脚本里保留一段 RAM 区域,两边都映射成同一个地址),要么先写入 Flash 的一个标志区,要么通过寄存器传递。我用下来最稳的是在 RAM 里指定一个结构体区域,Boot 写入,App 启动后读取,读完再清标志,这样既不占 Flash 擦写次数,也不怕复位清零。
5.4 升级流程中掉电了怎么办:备份区、双 Bank 与回滚
IAP 升级最怕的不是写错,而是写一半停电。如果 App 区在擦除过程中掉电,Flash 里是一片残废——既没有新固件,也没有旧固件,设备变砖。靠再上电也无法恢复,因为 BootLoader 跳转时发现 App 非法,但它手里没有可用的固件。
主流方案有三级:
- 升级期间只能写在 App 的备份区/下载缓存区,全部写完并且校验 CRC 通过后,才把有效标志置位,复位后由 BootLoader 做一次搬运,把新固件搬到正式 App 区。这样即使中途断电,正式 App 区还是旧固件,还能跑。
- 双 Bank 方案(AB 分区):Flash 足够大时,把两个完整 App 分区交替使用(比如 STM32H7 系列很多型号支持双 Bank)。写 Bank B 不影响 Bank A 运行,写完置位切换标记,下次复位从 Bank B 启动。比“先搬移再运行”更快,也天然支持回滚。
- 运行时自搬运:在一些 Flash 分区紧张的设计里,App 可能把下载缓存放在 RAM 或外部存储,写正式区时只擦除一半、写一半。这方案对断电恢复要求高,一般配合两个标志位使用,复杂度高,不推荐新手一开始就挑战。
另外我还想提醒一个容易忽略的点:**BootLoader 在设计时要预留好 IAP 升级用的通信协议版本号,以及固件头部信息(比如魔数、版本、长度、CRC),别今天写了版本号,后天加字段,导致旧 Boot 不认新 App。**我见过不止一次产品现场升级失败,最后查出来是 Boot 与 App 协议的版本兼容性问题,而不是通信本身有问题。最好把协议头做成“可扩展”结构,兼容过去两年以内的所有版本。
5.5 国产 MCU 做 IAP 的差异点
GD32F103、HC32L136 做 IAP 和 STM32 原理一致,但有几个差异必须注意:
- Flash 擦除粒度和选项字节解锁方式不同,写 Flash 前除了要解锁 FLASH_CR 寄存器,有些芯片还要额外配置写保护位,如果出厂默认把所有扇区保护了,IAP 写不进去很正常;
- 中断向量表偏移的方式不完全一样,Cortex-M0/M3 内核都支持 VTOR,但部分老架构 MCU 没有标准的 VTOR 寄存器,要在启动文件里改中断向量基址宏,或者用厂商库提供的重映射接口;
- 看门狗的影响会被放大。IAP 写 Flash 耗时较长(擦一个扇区是以毫秒计的),如果看门狗超时时间设置太小,写 Flash 过程中就喂不了狗,直接被复位,升级必然失败。做 IAP 设计时,一定要把升级期间的狗处理策略想好,严格讲这属于系统级设计,不是简单打开看门狗就算完事。
6. 三种方式怎么选:从样机到量产的组合打法
绕了一圈,最后落到选型。借用一张对比表把三者的全貌浓缩一下:
| 维度 | ICP | ISP | IAP |
|---|---|---|---|
| 编程主体 | 外部调试器 | 芯片内部 BootROM | 应用自身 |
| 典型工具/接口 | SWD/JTAG,J-Link、ST-Link、脱机烧录器 | 串口/USB,厂商 ISP 软件 | 自研 BootLoader + 通信接口 |
| 是否需要预置程序 | 不需要 | 不需要(BootROM 出厂自带) | 必须先跑一个 BootLoader |
| 硬件依赖 | 调试口引出(2~5 根线) | 启动引脚 + 通信接口 | 通信接口,最好留升级按键/命令 |
| 烧录速度 | 快(MHz 级时钟) | 中(受串口波特率限制) | 取决于通信带宽和 Flash 速度 |
| 适用阶段 | 研发调试、产线量产 | 产线低成本烧录、现场恢复 | 出厂后远程升级、OTA 维护 |
| 主要风险 | 调试口被锁死、接插件可靠性 | BootROM 协议固定、速度慢 | 升级掉电变砖、Flash 分区规划失误 |
产品工程师问得最多的一个问题是:我到底该给产品留哪个烧录口?我的答案很直接,不一定只留一个,三样可以共存:
- 研发和返修阶段:无条件保留 SWD 调试口,这是所有问题排查的兜底。哪怕产品量产后不接调试器,PCB 上留一组测试点就够,不占什么空间。
- 产线量产:首选脱机 ICP 烧录器 + 治具,速度快、防呆好;如果产品本身必须引出串口且调试口不方便开,那 ISP 串口烧录也是成熟选择,只是速度慢,需要按产能评估节拍。
- 出厂后升级:IAP 是唯一可行路线。除非你的产品允许快递回来拆壳烧录,否则远程 OTA 必须依赖 BootLoader 架构。就算不打算做 OTA,我也建议预留 IAP 能力——新产品第一批固件有 bug 是常事,能用远程升级止血和派工程师上门拆机,是两个不同的商业成本量级。
最后列一份避坑清单,算是我这些年被芯片烧录反复"教育"出来的经验:
- 焊接完先确认供电,再谈烧录。一个常见现场是 SWD 三根线接好了,但 VCC 没共地或目标板没上电,调试器识别不到芯片,许多人第一反应是换调试器、换线,其实先量一下 GND 通不通,往往最快。
- BOOT 引脚别悬空。很多 ISP 模式下不上电的问题,查到最后都是 BOOT 引脚悬空受干扰,导致进入随机状态。MCU 的启动配置引脚一般都有内部上下拉,但外部环境复杂时仍可能漂移,量产设计不要省这颗电阻。
- 调试口被读保护锁死时别慌。多数芯片提供 ISP“全片擦除”可以解除读保护,代价是 Flash 内容全空。如果产品里存储器有校准信息、MAC 地址等出厂数据,全片擦除会一起干掉,量产时要评估这个风险。
- Flash 是有擦写寿命的。NOR Flash 寿命常见 10 万次擦写,听起来很多,但 OTA 天天升级、调试时反复全片烧写,几个月也可能磨掉一笔。IAP 升级方案要尽量做到按需擦除而不是整片频繁擦写。
- IAP 跳转前检查外设状态。如果 BootLoader 里初始化了 DMA、定时器、UART,跳转前最好逐个复位到默认状态或直接关掉。否则 App 启动时外设寄存器还是 Boot 留下的配置,很容易出现“诡异”的首次运行异常。我习惯在跳转函数里把所有用到的外设反初始化一遍,代价只是多几行代码。
- 固件校验一定要做。不管是 ISP 还是 IAP,都要有完整的校验环节:传输层 CRC、写入后回读、完整性校验,三者缺一不可。省了这个环节,你省下来的时间会在现场故障排查时十倍还回去。
芯片烧录看着是个小事,本质却是嵌入式系统的“第一脚油门”。新手在这个阶段最容易犯的错是想快速跳过原理直接点“烧录”按钮,结果遇到问题就只会断电重来。真正把 Flash 控制器、启动模式、Vector Table、BootLoader 分工这层窗户纸捅破之后,你会发现自己面对的不再是玄学,而是一套环环相扣、完全可以推理的系统。如果你正准备从 51 或 STM32 入门做第一个产品,建议花一个下午的时间,把 DataSheet 里“Memory Map”和“Boot Configuration”两章从头到尾读一遍,再回头玩烧录,会比看十篇教程都管用。