ARTICLE DETAIL

资讯详情

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

ISP、ICP、IAP三种芯片烧录方式深入解析:从原理到实战选型

ISP、ICP、IAP三种芯片烧录方式深入解析:从原理到实战选型 新手接触单片机或者嵌入式开发几乎都会在芯片烧录这个概念前懵上一阵子。ISP、ICP、IAP这三个缩写长得像三胞胎查资料的时候解释又经常写得云里雾里。我第一次接触的时候也分不清只知道“反正能把代码弄进去就行”直到后来在项目里把三种方式都摸了一遍才彻底搞明白它们到底在解决什么问题。这篇文章我就用大白话配合实际使用场景把ISP、ICP、IAP一次讲透。讲完概念不是重点重点是你得知道写代码的时候选哪个方式、焊板子的时候留什么接口、量产的时候用哪种方案这些才是真正要命的实操问题。1. 烧录的本质把代码变成芯片的“本能反应”先抛开那些缩写想清楚一件事芯片烧录到底在干什么。一个芯片要跑起来不是说通了电它就知道自己要干嘛。你得先告诉它“你上电之后先读这一段指令然后按照这些指令去控制引脚高低电平、去处理数据。”这些指令就是我们写的代码编译出来的机器码本质是一串存在存储器里的二进制数据。烧录的本质就是把这串数据写入芯片内部的存储器。这个存储器有个关键特性掉电不丢失。否则你每次拔电重启代码就没了那芯片就是个废物。所以烧录真正的核心动作是往非易失性存储器里写数据。这里面引出一个很容易被忽略的点——不是所有芯片都能随便烧录。早期的OTP芯片One Time Programmable只能烧录一次写进去就永远锁死适合那种出厂前就要固化逻辑的产品。现在的MCU基本都是Flash存储可以反复擦写方便开发调试也方便产品做软件升级。Flash存储器的特点在于它分块管理写入之前必须先擦除。这就好比你在一张写满字的纸上要修改某个段落不可能直接在原字上覆盖必须先把那一块区域涂白再重新写。芯片烧录的过程实际上就是擦除写入校验三步擦除把目标Flash区域的旧数据全部清掉还原成全1状态。写入按照地址顺序把新数据写进去。校验把写入的内容读回来和源数据比较确认有没有写错。明白了这个底层逻辑再来理解ISP、ICP、IAP就轻松多了。它们本质上是三种不同的“往Flash里写数据”的方式区别只在于谁在控制这个写入过程、通过什么接口写入、在什么时机使用。2. 用生活类比秒懂三大烧录方式的核心差异为了把ISP、ICP、IAP的关系说清楚我用一个生活化的场景来类比。想象你手里有一个“存储介质”需要把一份重要资料放进去你有三种途径。第一种你把存储介质从设备上拆下来放到一个专用的读写器上通过物理接触的方式把资料写进去写完了再装回去。第二种存储介质留在设备里设备本身有一个“引导程序”你通过设备的通信口比如网口、串口把资料传给它它帮你转存到存储介质里。第三种设备已经在正常运行了它在运行过程中自己发现自己需要更新资料于是自己从某个地方下载新资料自己完成替换。对应到芯片烧录ICPIn-Circuit Programming在电路编程芯片焊在板子上通过专门的编程器用SWD、JTAG等专用调试接口直接操作芯片内部的Flash控制器完成烧录。相当于第一种不需要芯片自身跑任何程序编程器直接控制芯片硬件写Flash。ISPIn-System Programming在系统编程芯片通过串口、SPI、I2C等通信接口接收来自外部主机通常是电脑或上一个MCU的数据由一块出厂固化在芯片里的“引导程序”Bootloader接收数据并写入内部Flash。相当于第二种芯片自身参与写入过程但写入动作是由出厂预设的Bootloader完成的。IAPIn-Application Programming在应用编程芯片正在运行用户自己的应用程序应用程序通过某种通信方式获取升级包自己把自己所在的Flash区域的一部分进行更新。相当于第三种用户程序自己完成对自己的“部分重写”。这里有一个最核心的区别很多人没意识到ICP不需要芯片里有任何程序ISP需要芯片里出厂预置的BootloaderIAP需要芯片已经在运行用户程序。用大白话说就是ICP是“外部遥控器直接改数据”ISP是“芯片里自带了一个接收员帮你存数据”IAP是“程序自己动手更新自己”。这个差异决定了它们的使用场景完全不同烧录方式谁在控制写入需要芯片内有程序吗典型接口适用场景ICP外部编程器硬件直接控制不需要SWD、JTAG开发调试、工厂初次烧录ISP芯片内出厂Bootloader需要出厂引导程序UART、SPI、I2C量产烧录、固件升级IAP用户应用程序自己需要用户程序运行任意通信接口产品在线升级OTA3. ISP烧录深入拆解藏在芯片里的“引导程序”ISP这个词是新手最先接触到的因为很多单片机开发板的下载方式就是ISP。很多人拿STM32F103C8T6用串口下载程序用的就是ISP方式但根本不知道自己是在用ISP。3.1 ISP的底层工作机制STM32这类芯片出厂时Flash里有一段谁也删不掉的Bootloader。这段程序由芯片原厂固化作用是监听指定的通信接口等待接收外部主机发来的固件数据包然后按照协议解析、写入Flash。当芯片上电或复位时它会检测“启动引脚”Boot0、Boot1的电平状态决定从哪里开始执行代码从Flash启动正常从用户程序区启动跑用户自己的代码。从System Memory启动进入出厂Bootloader区执行原厂引导程序等待烧录。以STM32为例将Boot0拉高、Boot1拉低再复位芯片就会进入System Memory执行ISP Bootloader。这时你用串口连接芯片的USART1通常就是PA9、PA10通过专用软件比如STM32CubeProgrammer或老款的Flash Loader Demonstrator发送固件数据Bootloader接收后写入Flash。这个过程的特点是烧录的“主控权”在芯片自己的Bootloader手里外部工具只是个搬运工。3.2 串口ISP最容易被忽略的三个坑做串口ISP烧录我踩过的坑比想象中多。第一个坑是电平匹配。很多芯片的串口是3.3V电平但USB转串口模块如果没做电平转换输出可能是5V。直接接上去短期可能没问题但长期用或者在批量产线上很容易把芯片的引脚打坏。后来我统一用带电平转换的隔离模块或者干脆用STM32自带的USB DFU方式替代减少硬件层面的风险。第二个坑是boot引脚状态。有些板子设计的时候没有把Boot0和Boot1的跳线帽或者拨码开关引出来或者设计了但是位置很憋屈。导致烧录一次要拆外壳、拨跳线、复位、烧录、再拨回来折腾得要死。后来画板子的时候我干脆把Boot引脚的跳线做成默认下拉电阻焊盘短接的形式或者用双刀双掷开关把“正常启动”和“ISP烧录”两个状态做成拨码切换方便很多。第三个坑是串口烧录的时序要求。STM32的串口ISP不是上电就在等数据的Bootloader启动后会先发一个0x7F字节等待主机回应0x79建立同步握手之后才开始传输固件。所以烧录软件必须在芯片复位后的极短时间内完成握手。有些国产的USB转串口芯片延时比较大就会导致握手失败造成“一直连不上”的现象。遇到这种情况可以试试在软件里勾选“DTR/RTS自动复位”选项让软件控制复位时序。3.3 什么时候用ISP更合适ISP最大的优势是不占用调试引脚只占用一个串口。对于只有UART接口的芯片比如很多8位单片机、蓝牙SOCISP可能是唯一的烧录途径。ISP在量产时也很有优势因为产线工人不需要接调试器只需要一个治具探针对准串口焊盘或用免焊接探针就能完成烧录。这种方案比ICP快而且不需要每条板子都焊接调试接口的排针省成本。4. ICP烧录深入拆解外部编程器直接操控FlashICP就是大家最熟悉的“用ST-Link/J-Link烧录”的方式。开发STM32的时候插上ST-LinkKeil点一下下载程序就写进去了。但你有没有想过ST-Link是怎么做到这件事的4.1 ICP和JTAG/SWD的关系ICP使用的物理接口是JTAG或SWD。这两个接口是调试接口不仅支持烧录还支持在线调试、断点设置、变量查看。JTAG是一套完整的标准测试协议使用5根线TCK、TMS、TDI、TDO、TRST。SWD是ARM公司针对Cortex-M系列推出的精简版调试接口只需要2根线SWCLK、SWDIO。现在绝大多数STM32开发都直接用SWD因为占用引脚少、速度快。关键点在于ICP烧录是通过调试接口由外部编程器直接发出指令控制芯片内部的调试访问端口DAP和Flash控制器。这个过程中芯片CPU本身是停止的不执行任何程序。编程器通过DAP接口向Flash控制器写入数据完全绕过程序层面。用更直白的话说ICP就是“绕过了芯片自己的软件从硬件层直接改写Flash”。4.2 ICP烧录速度更快为什么做了这么多年的烧录我明显感觉到同型号芯片用SWD烧录比串口ISP快很多。原因在于接口速率和协议开销两方面SWD时钟可以跑到几MHz甚至更高数据线只有一根但传输是串行比特流配合硬件层的流水线处理实际吞吐很高。ISP走的是串口Bootloader协议除了数据本身还要处理同步握手、校验、应答、地址信息等打包格式每包数据都有额外开销。举个例子烧录一个64KB的固件到STM32F103用串口ISP大概需要20秒左右115200波特率用ST-Link SWD只需要不到5秒。在产线上这个时间差距非常可观。4.3 量产时是否会选ICP很多开发板爱好者习惯了一根ST-Link走天下对量产的理解还停留在“插上调试器下载”的阶段。实际上量产烧录如果直接用ICP有几个现实问题每个工位需要配备一个调试器ST-Link/J-Link成本高于串口转接板。SWD接口对连接稳定性要求高探针接触不良容易造成烧录失败。需要额外占用产线工人的操作步骤对准调试接口效率低于特制的自动化烧录治具。所以工厂量产通常有两种做法。第一种是先用ICP把Bootloader和应用程序一次性烧录完然后贴上封条出货第二种是只在产线用ICP烧录Bootloader之后的程序更新全部走ISP或IAP。第一种适合出厂后不再升级的产品第二种适合需要售后升级的产品。没有绝对优劣取决于产品定义。5. IAP烧录深入拆解程序自己更新自己如果说ISP和ICP是“人拿着工具去烧录”那IAP就是“设备自己给自己烧录”。这也是物联网产品实现OTA升级的基础。5.1 IAP的核心架构设计IAP的原理要复杂一些但说白了也容易理解。Flash空间被划分成两个区域Boot区引导区存放IAP程序功能是接收新固件、写入App区。App区应用区存放用户实际业务逻辑代码。芯片上电后首先执行Boot区的IAP程序。IAP程序判断是否需要升级不需要升级跳转到App区执行用户正常逻辑。需要升级通过UART、SPI、WiFi、蓝牙或其他接口接收升级包写入App区完成后跳转到App区。所以IAP程序的职责非常明确它是芯片里的“自助升级管理员”。App程序自己不能直接覆盖自己正在执行的Flash区域这是硬件限制所以必须借助Boot区的程序来执行写入操作。5.2 IAP跳转最容易翻车的地方中断向量偏移这是IAP开发中最经典的坑也是很多新手第一次接触IAP时必然踩的。当芯片从Boot区跳转到App区后App区的程序开始执行。问题在于如果App区的代码里用到了中断定时器中断、串口中断、外部中断中断发生的时候CPU去哪个地址找中断服务函数中断向量表的位置是编译时确定的。如果App区的代码编译时中断向量表默认放在Flash的起始地址0x08000000这是STM32的默认情况那么芯片一旦发生中断它还是会跑回Flash开头去找中断向量。但那个位置现在是Boot区的代码不是App区的中断向量表——结果就是中断一触发程序就跑飞了。解决办法是在App程序中重新定位中断向量表SCB-VTOR APP_FLASH_BASE; // APP_FLASH_BASE是App代码起始地址在STM32上这个寄存器用来告诉CPU“中断向量表搬到了哪里”。在App代码的初始化阶段必须先设置VTOR指向App区自己的中断向量表地址然后才能使能中断。需要注意这个操作依赖芯片具体型号。有的芯片比如一些国产MCU没有VTOR寄存器那就只能通过其他手段处理比如在Boot区做中断转发或者把中断向量表拷贝到RAM。做IAP之前第一步就该确认你选的芯片是否支持向量表重定位。5.3 IAP升级时定义的变量复位后的状态标题相关的热搜词里有一个问题“iap boot里面定义的变量复位后会怎样”。这个问题很有价值是IAP开发中真正会困扰人的点。在Boot区定义的全局变量在芯片复位后会被初始化按C语言标准全局变量在main之前初始化。但这里的“初始化”分两种情况如果是普通全局变量默认初始值为0或者你指定的初值。这部分数据存在Flash的初始化段里上电后由startup代码拷贝到RAM。但有一种情况容易出错Boot程序里定义了一个用于“标记是否需要升级”的变量然后跳转到了App区。App区执行完成后想进行软件复位NVIC_SystemReset让芯片重启进入Boot区。重启后这个变量会被重新初始化为默认值。那么这个“是否需要升级”的标记就丢了。如果你想在重启之后还能知道“上电前要进入升级模式”这个标记必须存到掉电不丢失的地方写入Flash的一个特定扇区。写入备份寄存器Backup Register。用RTC的备份域存。这个细节在真实的IAP产品调试中反复出现。我自己的第一版IAP就吃过这个亏升级标志放在RAM里一重启就丢怎么都进不了升级模式排查了半天才发现是变量的存储位置错了。5.4 IAP的最佳实践双区备份和安全机制物联网产品做OTA升级最怕的是升级写到一半断电了导致App区数据损坏设备变砖连Boot都没有了或者Boot被擦了。如果要产品可靠IAP必须考虑“防变砖”机制。推荐的做法是双区App设计App A区当前正在运行的程序。App B区用来接收新固件的区域。升级流程是把新固件先完整写入B区校验通过后记录“升级标志”到Flash或备份域然后复位Boot程序检查到标志后从B区启动。这样做的好处是即使升级过程中断电B区数据损坏A区仍然是完整的设备重启后Boot检测到A区有效继续从A区启动不会变砖。等下次有机会再重新下载新固件。对于Flash容量较小的芯片做不了双区那至少也要保证升级包在接收过程中有CRC校验接收完再整体校验一次全部通过才执行擦写。把“接收固件”和“写入Flash”分成两步而不是边收边写能显著降低变砖概率。6. 实战选型手头的场景该用哪种烧录方案讲了这么多概念最终要落到实际项目里怎么选。我根据自己做过的几种产品总结一下不同阶段的选型逻辑。6.1 开发调试阶段开发阶段调程序是常态这时候必须用ICPSWD。理由很简单SWD支持在线调试、断点、单步烧录速度又快。而且开发阶段要频繁改动代码ICP不需要动任何跳线点一下就下载体验好。我建议所有做MCU开发的人手头常备一个ST-Link或者J-Link别省这个钱。即使你用的是支持串口ISP的芯片开发阶段也尽量用ICP调试体验天差地别。6.2 小批量生产几台到几十台如果你的产品出厂就十几二十台量不大用ICP烧录是最省事的。保留开发用的烧录方式画板的时候预留SWD接口的测试点生产时用探针治具压上去烧录。这种方式不需要额外开发Bootloader和上位机工具成本最低。6.3 大批量生产几百台以上到了这个量级必须考虑产线的效率和防呆。我的做法是分两种情况产品有外壳出厂后不打算开放升级ISP治具烧录比较合适。因为产线工人只需要放置板子、按下烧录按钮系统自动完成全部烧录流程。ISP方式可以用便宜的串口线替代昂贵的调试器产线成本低。产品需要售后升级或者OTA先按ICP方式烧录Bootloader再通过ISP或者后续的IAP方式升级App。初始的Bootloader必须用SWD烧录因为此时Flash里是空的串口Bootloader也是出厂自带的但你想烧录自己的IAP Boot就得用ICP把IAP引导程序写进去。6.4 远程升级场景产品已经卖到用户手里了ISP和ICP都接触不到硬件只能靠IAP。通过网络、蓝牙、串口、甚至USB把升级包传给设备运行在设备上的App程序收到升级包后触发软件复位让Boot程序接管完成写入。这就是市面上一堆智能硬件所谓“固件升级”的底层机制。7. 手把手实验用串口ISP给STM32烧一段最简单的程序前边的概念都说了光看不练还是容易忘。这里我提供一个完整的串口ISP烧录流程你可以跟着操作一遍加深对ISP机制的理解。准备工具一块STM32F103C8T6最小系统板。一个USB转串口模块CH340即可。三个杜邦线。STM32CubeProgrammer软件。操作步骤将Boot0引脚接到3.3V使芯片上电后强制从System Memory启动。将USB转串口模块的TX接到芯片的PA10USART1_RXRX接到PA9USART1_TXGND接GND。注意交叉连接这是新手最容易搞错的地方。把USB转串口模块插到电脑打开设备管理器确认端口号。打开STM32CubeProgrammer连接方式选UART波特率选115200选择刚才识别的COM口点击Connect。连接成功后点击“Erase”全片擦除然后选择编译好的hex文件点击“Download”。下载完成后把Boot0跳线恢复为0V按下复位键观察板载LED是否运行新程序。整个过程能顺利跑通说明你确实理解了ISP的原理——芯片上电时Boot0引脚的电平状态决定了它去执行出厂Bootloader还是用户程序串口只是传输数据的通道。一个值得玩味的细节擦除Flash是全片擦除还是只擦需要写入的区域这两个选项在CubeProgrammer里都有。如果芯片里已经有其他Bootloader或者有需要保留的校准数据就不能全片擦除必须用“按地址擦除”或者“只擦除目标扇区”。这就是量产和保护性烧录的重要区别。8. STM32H750/国产MCU的IAP特殊之处热搜词里有两个具体型号——STM32H750VBT6和HC32L136。顺带聊一下这些芯片在IAP上有什么不一样的讲究。STM32H750VBT6是很多做HMI项目或者复杂嵌入式系统会选的芯片。它在IAP上的特殊之处在于片上Flash只有128KB但实际运行代码往往超过这个容量很多人会把代码放外部QSPI Flash里。因此它的IAP策略通常是分级启动Boot区放在内部FlashApp代码放在外部QSPI FlashBoot负责初始化QSPI并加载App。这种情况下IAP升级的不只是内部Flash区域还包括外部存储介质。值得注意的是H750的中断向量表默认位置依然是内部Flash起始地址如果App放在外部QSPI中断向量表的定位就要配合QSPI的映射特性进行处理否则中断一触发就跑飞。而且外部Flash和内部Flash的擦写逻辑、时序完全不同写IAP时要额外处理QSPI Flash的初始化、读取、擦除和写入函数。HC32L136这类国产MCU往往主打低功耗、低成本。它的IAP实现方式与STM32大体类似但需要特别注意两点一是国产MCU的Flash擦写规格可能和ST不同写入前是否需要解锁、擦除的最小力度是否按扇区、Flash磨损寿命如何都需要去数据手册里确认二是很多国产芯片并没有像STM32那样完善的Bootloader固件和配套烧录工具也许ISP不开放也许出厂Bootloader不具备串口烧录功能必须从ICP开始引导这一点选型时要提前确认清楚。9. 从烧录到调试ISP、ICP、IAP的一次性总结回顾三个概念用一句话分别概括ICP外部编程器在硬件层面直接操作Flash不需要芯片里的任何软件适合开发和初始化烧录。ISP芯片出厂自带的Bootloader通过通信接口接收数据并写入Flash适合量产和现场简易升级。IAP用户程序自己配合Boot程序完成对自身存储的更新是远程升级和OTA的基础。我个人在实际项目里的体会是三种方式不是互斥的而是组合使用的。开发用ICP、量产用ISP、远程升级用IAP一个成熟的产品往往三条路全都打通。新手学这三个概念不需要死记硬背协议细节先把“谁在控制写入”想明白自然就分得清了。如果你正准备给产品加上固件升级功能建议先做一个最小实验把Flash分区画好写一个最简Boot程序只做跳转写一个最简App程序点亮一个LED先用ICP把Boot烧进去再用IAP方式把App烧进去跑通了再逐步加复杂度。这条路走通之后你会发现ISP、ICP、IAP这三个词已经从“概念”变成了你手里的工具。
返回列表