前言
我们常见的MCU / CPU 代码烧录方式主要有以下三种:
- ICP(In Circuit Programing):在电路编程,可通过CPU的Debug Access Port 烧录代码,比如ARM Cortex的Debug Interface主要是SWD(Serial Wire Debug)或JTAG(Joint Test Action Group);
- ISP(In System Programing):在系统编程,可借助MCU厂商预置的Bootloader 实现通过板载UART或USB接口烧录代码,比如STM32存储映射Code分区中的System memory可以预置厂商的Bootloader,让MCU支持通过UART下载(不限于UART,具体由厂商预置Bootloader实现而定);
- IAP(In Applicating Programing):在应用编程,由开发者实现Bootloader功能,比如STM32存储映射Code分区中的Flash本是存储用户应用程序的区间(上电从此处执行用户代码),开发者可以将自己实现的Bootloader存放到Flash区间,MCU上电启动先执行用户的Bootloader代码,该代码可为用户应用程序的下载、校验、增量/补丁更新、升级、恢复等提供支持,如果用户代码提供了网络访问功能,IAP 还能通过无线网络下载更新代码,实现OTA空中升级功能。
一、ICP 与 JTAG / SWD
ICP 主要通过CPU的DAP(Debug Access Port) 烧录代码,下面以ARM Cortex-M3/M4 为例,展示Debug Interface 如下:
ARM Cortex 内部包含了CoreSight 调试架构,CoreSight 包括调试接口协议、调试总线协议、对调试组件的控制、安全特性、跟踪接口等。以前的ARM 处理器都提供JTAG 接口,通过它来控制对寄存器和存储器的访问,CoreSight 则通过DAP(Debug Access Port) 来控制处理器上的总线逻辑。从上图也可以看出,CoreSight 除了提供Debug Interface,还提供了Trace Interface,Trace Interface 主要用来观察数据中间值的变化、跟踪指令的执行状态等,只能单向读取跟踪数据,属于非侵入式调试,不能用于烧录代码,因此本文不对此做过多介绍。
ARM Cortex 目前支持两种Debug Interface:
- SW-DP (Serial Wire - Debug Port):新提供的串行线调试接口SWD,只需要两条信号线(SWCLK、SWDIO);
- JTAG-DP (Joint Test Action Group - Debug Port):广为使用的联合调试接口JTAG,至少需要四根信号线(JTCK、JTMS、JTDI、JTDO,JTRST 为可选信号线);
- SWJ-DP (SW + JTAG - DP):支持SW-DP 与 JTAG-DP 两种接口协议。
STM32 同时支持SW-DP 和 JTAG-DP,也即支持的是SWJ-DP 调试接口协议,STM32-L4 的SWJ Debug Port 如下图所示:
从上图中可以看出,JTAG-DP 与SW-DP 两个接口都需要提供Clock 驱动信号,二者的数据传输引脚不同,SW-DP 接口使用半双工的SWDIO 引脚传输数据,JTAG-DP 接口使用两个单工的JTDI 和JTDO 引脚组成全双工通信。JTAP-DP 除了时钟引脚和数据传输引脚外,还有个重要的引脚JTMS 测试模式选择引脚,可以控制TAP(Test Access Port) 状态机的切换,JTRST 主要用来对TAP 状态机进行复位,为可选引脚(因此有四线JTAG 与五线JTAG 之分),JTMS 也可以实现TAP 状态机的复位。JTAG-DP 与SW-DP 引脚的功能描述如下:
早期的MCU 是可插拔的,向其内烧录代码时常需要将其拔下来,借助烧录器或仿真调试器通过Debug Interface 将代码烧录进MCU 后,再把芯片插回到电路板上。后来MCU 直接焊接在电路板上,电路板上直接引出了Debug Interface,比如常见的JTAG 和 SWD 接口,可以借助JLINK 或 STLINK 等仿真器,通过JTAG 或 SWD 接口直接将代码烧录到MCU 中,省去了MCU 插拔操作,方便了代码烧录和调试操作。
不同的IC 厂家会自己定义自家产品专属的JTAG 接口,来下载和调试程序。嵌入式系统中常用的有20pin、14pin、10pin 等JTAG 接口类型,不同类型的JTAG 接口都包含前面提到的五个引脚,另外包括VRef 和 GND 等引脚,它们的不同之处主要在于GND引脚的数量、一些用户自定义引脚、保留引脚等。一般JTAG 接口同时支持 SWD 接口,但有些主板受空间限制,只提供了SWD 接口,只需要四个引脚,大大节约了空间。
IC 厂家提供的部分开发板上直接集成了 JLINK 或STLINK 模块,相当于将JLINK / STLINK 仿真器内置到开发板上了(比如STM32L4 Pandora 或 NRF52 DK),不再需要额外的仿真器(也不再需要板载JTAG 或 SWD 接口),直接通过USB 线连接电脑,就可以方便的进行代码烧录和调试,对于手头没有仿真器的开发者更加友好,毕竟正版仿真调试器价格还是有点贵的。
二、ISP 与 Boot Mode
ISP 可以通过USB接口(可以是UART协议或USB协议等)直接烧录代码,ARM Cortex 提供的Debug Interface 并不支持UART 或USB 协议,这就需要IC 厂商预置UART 协议或USB 协议代码,让MCU / CPU 支持UART 通讯或USB 通讯。UART 协议比较简单、传输速率比较低,比如STM32 这类MCU 支持UART 协议烧录代码;USB 协议相对复杂、传输速率比较高,比如高通骁龙这类CPU 支持USB 协议烧录代码。
以STM32 为例,先看看有哪些启动模式:
STM32 有三种Boot modes 开始执行代码:
- Main Flash memory:STM32内置的Flash,一般我们使用JTAG / SWD 烧录代码都是直接烧录到这个存储区间,重启后也直接从这里的代码开始执行;
- System memory:这种模式启动的程序功能是由厂家设置的,STM32 在出厂时由ST 在这个存储区间内部预置了一段BootLoader(也即ISP 程序),这段程序出厂后无法修改。厂家提供的BootLoader 一般支持UART 协议,可以让我们直接通过串口将程序代码烧录到Main Flash memory 中;
- SRAM1:这个启动模式一般用于程序调试,假如我只修改了代码中一个很小的地方,重新烧录到Flash比较费时,可以从STM32 内存中启动代码,进行快速的程序调试,等程序调试完成后,再将程序烧录到Main Flash memory 中。
Main Flash memory、System memory、SRAM1 的存储区间分布如下图所示(在博文:存储管理与虚拟内存中也有介绍):