
聊到芯片烧录很多刚开始玩单片机的朋友第一反应是——不就是把程序写进芯片嘛用下载器点一下烧录就完事。真到项目里需要自己设计批量烧录、远程升级、Bootloader 时才发现里面水挺深。尤其是 ISP、ICP、IAP 这三个缩写网上说法五花八门有人把 ISP 当图像信号处理有人把 IAP 当苹果内购退款同一个词在不同场合完全是两码事。这篇文章就把芯片烧录这件事从头讲透重点说清 ISP、ICP、IAP 三种方式到底怎么工作、各自适合什么场景、实操中容易踩哪些坑。新手能看懂做了一段时间嵌入式但没系统梳理过烧录体系的朋友也能借此把知识串起来。1. 先搞清楚烧录到底在烧什么1.1 烧录的本质是向非易失存储器写入数据芯片上电运行后CPU 执行的指令和使用的常数数据都存在非易失性存储器里。单片机里最常见的是内部 Flash也叫闪存有些芯片还有 EEPROM或者一次性可编程的 OTP 区。烧录的本质就是把编译生成的二进制固件通常转成 hex 或 bin 文件按照芯片规定的时序和协议写入到这些存储器中。你可以把 Flash 想象成一块可以反复擦写的白板。和普通白板不同的是Flash 写入前必须先擦除而且擦除有最小单位——很多 MCU 的 Flash 以页Page为单位擦除比如 STM32F103 大容量型号是 1KB/页GD32F103 也是 1KB/页STM32F407 则是 2KB/页。所以烧录不是打开文件–复制–粘贴那么简单而是要先擦除目标地址所在的页再把数据按 word 或半字写入最后还要读回校验。这就是为什么你在烧录软件里总能看到擦除、编程、校验这三个阶段。1.2 芯片出厂时并不是活的很多新手会以为芯片买回来里面就有程序其实一般 MCU 出厂时 Flash 是空白的除非厂商预烧了 Bootloader 或测试程序。芯片要运行用户程序前提就是先把可执行代码放进 Flash。这个过程就是烧录也叫编程Programming。烧录没问题芯片通电后才能按设计干活。顺带说一句Flash 是有擦写寿命的。多数 Cortex-M 系列 MCU 的 Flash 寿命标称大约 1 万次擦写虽然实际用下来往往会更多但研发阶段如果反复全片擦除频率太高也容易让这块芯片提前到寿命末期。我习惯的做法是调试小改动时用调试器增量下载不是每次都全片擦除真要全片擦也会尽量换一块测试专用的芯片来折腾。1.3 三种烧录方式是怎么来的ISP、ICP、IAP 本质上是解决程序怎么进 Flash的三种不同路径。ICPIn-Circuit Programming在线编程外部编程器通过调试接口SWD/JTAG直接控制芯片核心操作 Flash 控制器完成写入。芯片自身不需要先跑任何程序。ISPIn-System Programming在系统编程芯片出厂时在 ROM 里固化了一段引导代码Bootloader外部通过串口等接口向上位机完成握手上位机把固件传给 Bootloader由 Bootloader 写入 Flash。IAPIn-Application Programming在应用编程用户程序自己具备操作 Flash 的能力在芯片运行期间程序通过串口、CAN、以太网、USB 等接口接收新固件由程序自己写进 Flash然后跳转执行新程序。用生活化的比喻ICP 好比把硬盘拆下来挂到另一台电脑上直接分区装系统ISP 相当于电脑出厂预装了一个恢复引导工具你从 U 盘或网络引导它帮你装系统IAP 则像是操作系统运行中自己下载更新包、自己写系统盘、然后重启完成升级。三者解决的是不同阶段的需求后面一个个展开。2. ICP把编程器直接怼到芯片调试口上2.1 ICP 的原理与接口ICP 是嵌入式开发中最常用的烧录方式它依赖芯片的调试接口。Cortex-M 系列芯片基本都支持 SWDSerial Wire Debug和 JTAG。SWD 只需要两根信号线SWDIO、SWCLK加电源和地占用引脚极少实际项目里用得最多。JTAG 需要的线更多TMS、TCK、TDI、TDO 等但调试能力更强FPGA、ARM 核心等场合常见。ICP 能工作的关键是调试接口可以在外围电路不运行的情况下通过调试访问端口访问芯片内部的寄存器和 Flash 控制器。意思是哪怕芯片 Flash 是空的、程序跑不起来调试器照样能连上并烧写。这也是在线编程含义的一部分——芯片已经焊在电路板上不需要拆下来编程器接上就能写。2.2 编程器怎么选常见编程工具有 ST-Link、J-Link、DAP-Link、CMSIS-DAP以及各家厂商原厂工具比如 NXP 的 LPC-Link、GD 的 GD-Link。选型主要看两点是否支持你要调试的芯片型号以及是否需要高速调试特性。我自己的习惯是手头常用 STM32/GD32 等 Cortex-M 芯片一个 J-Link或兼容版基本通吃如果要低成本方案DAP-Link基于 CMSIS-DAP 协议十几块钱就能买到SWD 调试和下载完全够用如果芯片是国产小众型号优先用厂商推荐的工具因为有些芯片的 SWD 时序有特殊性第三方工具反而连不上。注意有的 MCU 在代码里把 SWD 引脚复用成了 GPIO或者开启了很高的读保护等级这时候 ICP 就可能连不上。解决办法之一是按住复位键在复位释放瞬间尝试连接很多调试器支持 connect under reset或者先用串口 ISP 方式把芯片读保护降级/擦除。2.3 ICP 实操流程以 STM32 ST-Link 为例接线方面SWD 最少接四根线SWDIO、SWCLK、GND以及 VCC目标板供电时可不接 VCC 仅作参考电平但建议接上特别是调试器需要检测目标电压时。接线顺序要注意共地不管用哪种调试器GND 必须连通。软件方面可以用 ST 官方 STM32CubeProgrammer也可以用 Keil MDK 的 Flash Download 功能。以 CubeProgrammer 为例选择 ST-LINK设置连接方式为 SWD频率可以先用 4MHz 左右试探点击 Connect能看到芯片型号、Flash 大小、读保护等级等信息加载 hex 或 bin 文件点击烧录软件会执行擦除、编程、校验三步烧录完成后直接按复位运行。这里有个细节选择烧录地址。hex 文件自带地址信息bin 文件则需要你手动指定起始地址。烧录到内部 Flash 的起始地址一般是 0x08000000STM32不同芯片可能不同务必查手册不要拿 STM32 的地址惯性套别的芯片否则烧进去直接跑飞。2.4 ICP 的优势与局限ICP 最大的优势是不依赖芯片里任何已有程序空片也能烧同时在开发阶段它不只是烧录工具还承载着断点调试、变量查看等功能所以它是研发阶段的首选。局限也很明显需要引出调试接口、需要额外的编程器现场维护时如果产品没有留调试接口ICP 就派不上用场。这时候就要引入 ISP 了。3. ISP利用芯片自带的 Bootloader 悄悄干活3.1 什么是 ISPISP 的全称是 In-System Programming指芯片在系统即焊在电路板上状态下通过芯片内部固化的引导程序完成对用户 Flash 的编程。这个出厂引导程序一般放在独立的 ROM/系统存储区用户程序无法覆盖它。正因为 Bootloader 是出厂就烧死的所以 ISP 有一个特点即使芯片 Flash 已经被擦空只要 Bootloader 仍在就能通过串口等接口把程序救回来。这相当于芯片自带了一个急救通道。不同厂商的 ISP 通道不同。STM32 的 ISP 主要是 USART串口另外也支持 USB DFU、CAN 等NXP 的 LPC 系列支持 UART、SPI、I2C、USB 等STC 单片机则主要通过串口下载。设计产品时如果留了串口就等于留了 ISP 通道。3.2 ISP 怎么让芯片听话进入引导模式关键问题是芯片上电后默认是执行用户 Flash 程序的那怎么让它先执行 Bootloader 而不是用户程序答案是用引脚电平或特定时序来切换启动模式。以 STM32F103 为例芯片有 BOOT0 和 BOOT1 两个引脚。BOOT0 拉高、BOOT1 拉低时芯片从系统存储器启动也就是进入串口 ISP 模式BOOT0 拉低时从用户 Flash 启动。所以 ISP 烧录的典型操作是把 BOOT0 置高BOOT1 置低复位芯片或重新上电使其从系统存储器启动打开上位机软件如 STM32CubeProgrammer 或 Flash Loader选择串口号和波特率软件与 Bootloader 握手成功后加载固件烧录完成把 BOOT0 拉回低电平复位运行。握手过程很有意思。STM32 的 ISP 协议中上位机会发送一个 0x7F 字节Bootloader 收到后如果波特率匹配且条件正常会回 ACK0x79和另一个 0x79。两次握手都通过才进入后续的擦写流程。这也是为什么 ISP 对晶振精度有要求——如果你的板子晶振偏差太大或者波特率设置过高握手就会失败。3.3 从 STC 的串口下载看 ISP 的另一个流派国内玩 STC 单片机的朋友一定熟悉 STC-ISP 这个软件。它的下载方式和 STM32 不太一样要求先断电点下载按钮再给目标板上电俗称冷启动。原因是 STC 芯片在上电瞬间检查串口 RXD/TXD 引脚的电平状态如果检测到合法的下载请求序列就停留在 ISP 模式否则正常启动用户程序。这种设计的优点是不需要专门的 BOOT 引脚对量产现场很友好缺点是必须人为制造上电时序自动化工装需要控制目标板电源。网上经常看到STC ISP 去弹窗之类的话题那说的是这个烧录软件本身的界面和推广弹窗的体验问题跟烧录原理没有关系但也侧面说明 ISP 软件工具的体验直接影响工程师日常效率。在 STM32 的 BOOT0/BOOT1 方案之外还有一类 MCU 通过**在软件里设置 Option Byte选项字节**来决定启动源或者支持在 Bootloader 中先判断某个通信接口是否有下载请求。不同芯片机制不一样做项目第一件事永远是翻芯片参考手册里的System Memory / Boot mode章节。3.4 别把ISP误解成图像信号处理或苹果的 IAP写这篇文章前我特意搜了一下发现ISP这个词在搜索结果里大量指向Image Signal Processor图像信号处理比如 ISP pipeline、富瀚 ISP 这种指的是摄像头图像处理链路里的 ISP 模块和烧录八竿子打不着。还有微信小程序虚拟支付 苹果 IAP 退款这里的 IAP 是 In-App Purchase应用内购买也不是芯片烧录领域里的 IAP。碰到这些术语时先看上下文再对号入座别在技术讨论里闹笑话。3.5 ISP 适合的场景ISP 不要求专用调试器只要 MCU 留出通信引脚如串口就能完成烧录。它非常适合量产烧录一台电脑加 USB 转串口批量烧录成本很低现场升级设备已经部署出去现场维护人员只有一台笔记本通过串口就能重新烧录恢复砖机Flash 里用户程序坏了只要 Bootloader 还在ISP 就是最后的救命通道。代价是 ISP 速度一般不如 ICP而且需要芯片出厂自带 Bootloader。有些芯片尤其是一些资源极小的 MCU可能没有 ISP 功能或者 ISP 只支持固定的串口引脚设计硬件时要提前确认。4. IAP让程序在运行中自己升级自己4.1 IAP 解决的是升级问题ISP 和 ICP 本质上都需要外部介入——要么插编程器要么手动进 Bootloader。但真正做产品的人都知道用户手里的设备不可能都拆开接串口。更合理的方式是设备联网软件自动检查更新下载完固件包自己完成 Flash 写入重启后运行新版本。这就是 IAPIn-Application Programming。IAP 的在应用编程含义是应用程序在运行过程中通过自身代码对 Flash 进行擦写。芯片不需要进入特殊模式也不需要外部编程器。这就对程序架构提出了要求——你必须把 Flash 空间规划好至少分成 Boot 区和 App 区甚至多个 App 区用于版本回滚。4.2 最小 IAP 系统的分区设计一个最典型的方案是两个分区Bootloader 区上电后先执行负责检查是否有新固件。如果有就通过串口/CAN/以太网接收数据并写入 App 区如果没有直接跳转到 App 区执行。App 区真正的业务逻辑代码。以 STM32F103 为例内部 Flash 从 0x08000000 开始。可以把 Bootloader 放在 0x08000000占 16KB 或 32KBApp 放在 0x08004000 或 0x08008000。App 编译时链接地址必须和烧录地址一致。如果 App 要支持升级后再次升级也就是 App 也能触发跳回 Boot还要考虑一套 App 请求升级 - 软件复位 - Boot 接管 的握手机制。需要注意的是中断向量表。Cortex-M 芯片的向量表默认放在 Flash 起始地址 0x08000000也就是 Bootloader 所在位置。App 要想正确响应中断必须把向量表偏移到 App 起始地址。Cortex-M3/M4/M7 可以通过设置SCB-VTOR实现SCB-VTOR APP_START_ADDR;Cortex-M0/M0 不支持 VTOR部分厂商芯片例外比如有的 M0 提供重映射寄存器所以需要把 App 的向量表拷到 SRAM 起始处再把内存重映射到 SRAM。具体做法厂商手册里都有但原理要明白中断向量表放哪CPU 中断时就去哪找入口。4.3 跳转代码和变量问题的深度剖析一个网上经常问的问题IAP Boot 里面定义的变量复位后会怎样先说结论如果是真正地复位重启比如调用了NVIC_SystemReset()或者硬件看门狗复位那么 Boot 的启动代码会重新运行C 运行库会初始化全局变量和 ZI 段Boot 中变量按照初始化规则重置。App 启动时重新执行自己的启动代码不会去用 Boot 的变量。但很多 IAP 跳转不是走完整复位而是软件直接跳转比如typedef void (*pAppFunction)(void); int main(void) { // Boot 阶段 uint32_t appStack *(volatile uint32_t *)(APP_START_ADDR); pAppFunction appEntry (pAppFunction)(*(volatile uint32_t *)(APP_START_ADDR 4)); // 跳转前关中断、复位外设 __disable_irq(); // 设置主栈指针并跳转 __set_MSP(appStack); appEntry(); }在这种跳转方式下系统并没有真正复位SRAM 里的内容不会被硬件自动清零。Boot 里定义的变量值仍然残留在原来的 RAM 地址上App 启动时如果恰好也用到了同一段 RAM启动代码会重新初始化自己的变量区域。换句话说Boot 变量的残留值对 App 没有实际意义App 不会主动去读取它们。但有一种合法传递方式Boot 和 App 约定一个固定 RAM 地址Boot 把升级状态写到那里App 启动时去读从而判断我是因为升级成功启动的还是异常复位启动的。这种约定的本质是 Boot/App 之间的通信协议不是普通的 C 变量作用域问题。真正容易出问题的反而是跳转前的外设状态残留。如果 Boot 里初始化了串口、开了中断跳转 App 时没有关闭App 启动后外设寄存器还处于旧状态中断可能会在 App 初始化完成前触发导致莫名其妙死机。所以跳转前最好这样做关闭全局中断把所有用过的外设恢复到复位默认状态关闭 SysTick 定时器设置好 MSP再跳转。4.4 从 IAP 到 OTA只差一个可靠的传输层IAP 解决了本地烧录问题OTAOver-The-Air则是在 IAP 基础上加了一个远程传输链路。比如设备通过 WiFi 或 4G 模块下载一份新固件暂存到外部 Flash 或 RAM 缓冲校验通过后再通过 IAP 流程写入内部 Flash。eth IAP 怎么实现就是在问以太网做 IAP 的思路。简单说两种做法Bootloader 内置精简协议栈比如用 UDP TFTPBoot 阶段和 TFTP 服务器通信直接下载固件到 Flash。好处是不需要 App 参与坏处是 Boot 代码量大、开发复杂App 负责下载然后跳 Boot 升级App 有完整网络协议栈下载固件包到外部存储设置一个升级标志复位后由 Boot 完成搬运和写入。这样 Boot 只需要支持从本地外部存储读写代码可以做到很小。不管哪种方案传输层都要考虑断点续传、CRC32/SHA 校验、固件版本比对、升级失败回滚。别小看这些我见过不少项目第一次做 OTA只在 Demo 环境跑通了一到弱网环境就翻车原因就是没有处理下载中断后的重试机制。4.5 不同芯片做 IAP 时要注意什么GD32F103 的 IAP思路和 STM32F103 一致Cortex-M3 内核有 VTOR支持分区跳转。但注意 GD32 的 Flash 擦写操作和 STM32 有细微差异尤其是解锁、擦除等待标志位判断直接用 ST 库代码大概率会出问题。用 GD 官方库或参考国产库适配。STM32H750VBT6 的 IAP这块芯片官方标称 128KB Flash内部实际存在的 Flash 容量可能更大但厂商不承诺给用户做 IAP 时千万不要按照网上那些把 H750 当 1MB Flash 用的方案来规划地址。量产品种就要以官方规格为准。H7 系列还支持双 Bank 特性可以在两个 Bank 之间做升级切换掉电变砖风险低但配置复杂需要在写 Option Byte 时格外小心。HC32L136 的 IAP华大小华半导体低功耗系列Cortex-M0 内核。M0 没有标准 VTOR所以中断向量重映射方案要参考厂商的参考手册。低功耗芯片做 IAP 时还要注意擦写 Flash 期间功耗会升高如果在电池供电场景下升级要确保电源能撑住瞬间电流升级过程中尽量禁用低功耗模式免得 Flash 操作到一半进 sleep。5. 三种烧录方式怎么选5.1 一表看懂 ICP / ISP / IAP对比项ICPISPIAP英文全称In-Circuit ProgrammingIn-System ProgrammingIn-Application Programming需要外部编程器需要ST-Link/J-Link 等不需要但要通信接口不需要程序自行完成依赖芯片出厂 Bootloader不依赖依赖出厂 Bootloader不依赖但要自己写 Boot/App是否需要改应用代码不需要不需要需要专门分区和跳转逻辑典型接口SWD/JTAG串口/SPI/USB/CAN串口/CAN/以太网/无线/USB能否烧录空片能能Bootloader 在 ROM不能至少 Flash 要先有引导程序现场升级便利性差要引出调试口中串口即可高支持远程开发成本低低高需要设计双区架构5.2 研发、量产、现场维护三个阶段怎么搭配研发阶段ICP 是主力。你需要在 Keil/IAR 里反复下载、断点调试没有比调试器更顺手的工具。如果用到 IAP 功能研发阶段也要验证 BootApp 跳转逻辑但日常改 App 仍走 ICP 直接把 App 烧到指定地址即可。量产阶段看产量和成本。几百片的小批量用 ICP 离线编程器或者 ISP USB 转串口都行大批量走自动化产线通常用离线编程器或全自动烧录机。离线编程器可以提前把固件导入生产现场不需要电脑工人只需插上目标板、按一下按钮、看指示灯。有些烧录机还支持探针压接不用焊排针大大提高效率。现场维护/产品升级ISP 可以用于工程师上门维护但更理想的还是设计时就内置 IAPOTA。产品联网后台分发固件用户体验和运维成本都是质的提升。5.3 烧录安全与加密是不可跳过的话题烧录不只是把代码写进去还涉及知识产权保护。Cortex-M 芯片一般都有读保护 RDP 和写保护 WRP。ICP 烧录后可以设置读保护等级防止别人通过调试接口把 Flash 内容读出来逆向复制产品。ISP 和 IAP 同样要考虑安全。ISP 的 Bootloader 如果没有任何校验别人拿到串口就能刷任意固件甚至读取 FlashIAP 的升级包如果明文传输抓包就能拿到完整固件。比较稳妥的做法是固件包做签名校验如 RSA/ECDSA 签名Boot/App 在写入前验证签名防止中间人篡改再配合 AES 等算法对固件加密即使抓包拿到的也不是明文。当然芯片里的加密密钥本身也可能被攻击没有绝对安全但至少做到别把厂家的出厂默认配置直接暴露在生产环境里。我见过不少项目量产固件里连读保护都没开撕开外壳引个 SWD 就能抄板损失惨重。6. 常见问题与避坑指南6.1 ICP 连不上芯片怎么办几种典型情况SWD 引脚被代码复用程序初始化时把 PA13/PA14 配置成了普通 GPIO。解决办法是使用调试器的 connect under reset或者在代码里加一个延时再在调试器连接后把引脚功能恢复芯片进入低功耗模式调试器连接前如果芯片已经 sleepSWD 不一定能唤醒。同样建议按住复位或使用复位连接方式读保护级别太高报错提示 RDP Level 1/2。Level 1 还能做全片擦除降级Level 2 基本锁死无法通过调试口恢复。这也是我为什么建议量产军工等高安全产品时提前规划好升级方式和烧录顺序不要最后把所有路都堵死接线太长或频率太高SWD 线超过 10cm 且频率拉满时特别容易接触不良。降到 1MHz 或者换更短杜邦线能解决很多奇怪问题。6.2 ISP 握手失败怎么排查ISP 的握手失败90% 出在三个方面BOOT 引脚没拉对确认芯片手册上的启动模式真值表注意 BOOT0/BOOT1 的上电时序。有的芯片不是简单电平选择还要配合复位时序串口 RX/TX 接反这几乎是新手最常见的问题。目标板发送引脚要接 USB 转串口的接收引脚接线图一定要对着原理图反复看波特率过高或晶振偏差如果板子上用的是内部 RC 振荡器误差可能达到 1%-2%串口波特率越高越容易握手失败。把波特率降到 9600 或 19200 再试成功率会明显提升。另外有的 ISP 程序要求目标板先供电、再打开软件有的要求软件先设置好、再上电。STC 的冷启动就是典型案例不能一概而论。6.3 IAP 跳转后死机怎么排查跳转到 App 后死机最常见的几个原因中断向量表没设置或设错地址Cortex-M3/4/7 检查SCB-VTOR是否等于 App 起始地址M0 系列确认重映射机制是否生效链接地址错误App 编译时的 Flash 起始地址和实际烧录地址不一致。看 map 文件确认第一条指令和向量表的位置栈指针初始化错误跳转前__set_MSP(appStack)里 appStack 必须从 App 起始地址的前四个字节读取读错一个字节跳转后栈就废了外设状态残留Boot 里初始化过的外设没有复位App 初始化到一半被中断打断。跳转前尽量恢复外设默认状态Flash 写保护未关闭App 区如果被写保护擦写失败代码根本没写进去。排查 IAP 死机最有效的手段是在 App 入口放一个 GPIO 反转看跳转后有没有真正执行到 App 代码。先确定问题出在没跳过去还是跳过去但初始化挂了再逐步缩小范围。6.4 量产烧录的现场坑量产烧录和实验室烧录是两码事节奏完全不同。以下几点请务必注意烧录顺序设计先烧录再贴片还是贴片后再烧录如果用的是 ISP 和串口通常贴片后烧如果用的是 Socket 离线编程器可以先烧再贴。先烧后贴要留意芯片引脚是否被污染影响接触工装供电稳定性烧录瞬间 Flash 写入的电流尖峰如果电源线太细或者稳压器裕量不够会导致烧录中途掉电变砖。产线工装电源质量一定要测过防呆设计探针治具要有方向防呆防止反插导致芯片损坏烧录工位要有三色灯提示红黄绿一目了然数据校验不可省量产烧录软件一定要开启校验功能烧完读回比对。哪怕多花几秒钟也比产品到客户手里跑不起来强。我做批量产品时还会在固件里写入生产批次号和序列号。这样不仅烧录时可以确认确实烧对了固件后续客户反馈问题时第一时间知道是哪批货、哪个生产工位排查效率高很多。这一招比单纯依赖烧录软件的成功率统计实在得多。芯片烧录这门手艺说到底就是在效率、成本、可靠性之间找平衡。研发阶段拿 ICP 暴力调试量产阶段用 ISP 或离线编程器追求低成本产品升级则靠 IAP 铺路把远程 OTA 的通道修通。新手刚开始不需要把三条路都钻研到很深的程度先把 ICP 玩熟再弄懂 ISP 的握手流程最后动手做一次 BootApp 的 IAP 跳转整个体系就通了。那些网上搜出来的isp pipeline苹果 IAP 退款绕过就好真正和你打交道的永远是这块 Flash 和它背后的启动逻辑。