内容包括ISP、IAP、ICP三种烧录方式的详细介绍,STM32单片机与宏晶STC单片机烧录方法,STM32单片机自动ISP的详细介绍(附电路原理图)。紫色文字是超链接,点击自动跳转至相关博文。持续更新,原创不易!
目录:
一、烧录方式简介
二、烧录方式详述
1、ISP:In System Programming
2、IAP:In Applicatin Programming( CAN总线实现stm32的IAP )
3、ICP:In Circuit Programing
三、相关总结
1、形象点的描述
2、STM32进入BootROM的方式
3、STM32自动ISP、RS232通信
1)自动ISP硬件电路 2)注意事项
附录1、STM32加密烧录
-----------------------------------------------------------------------------------------------------------------
一、烧录方式简介
单片机的烧录方式主要可以分为ICP(在电路编程)、IAP(在应用编程)以及ISP(在系统编程)。玩单片机的都应该听说过IAP、ICP和ISP这几个词。
ISP:In System Programing,在系统编程
IAP:In Application Programing,在应用编程
ICP:In Circuit Programing,在电路编程
JTAG(Joint Test Action Group)编程:通过JTAG协议进行编程
SWD(Serial Wire Debug)编程:通过SWD协议进行编程
UART编程:通过UART进行编程
--------------------------------
用一张图形象的表示一下,如下。
图1.1.1
从图上看,ISP和ICP是处于最顶层的技术。描述的是一种编程结构,所使用到的协议、通信端口等,不同芯片有不同的定义。
IAP在第二层,是一种编程方式。实现方式是将一段目标芯片可执行的代码通过某种通信协议下载到芯片RAM中并由芯片执行,由该代码实现具体操作以达到编程的目的。这种方式需要芯片支持通过某种通信协议。
对芯片的RAM进行读写并能控制其CPU。这是在编程结构下的一种编程方式,像AK100Pro、SmartPRO、5000U-Plus等烧录器,都用到了这种编程方式。
最下面的是硬件通信协议,UART是最早应用在单片机里面的串行通信技术。JTAG和SWD是ARM内核芯片兴起之后,逐渐流行起来的,这三种技术描述的是编程过程中硬件层使用的通信协议,是最底层的一些技术规范。
--------------------------------
用一个表格来对比这几种通信协议的特性:
协议种类 | UART | JTAG | SWD |
最高波特率 | 1.5M | 50M | 50M |
信号线 | 2 | 4 | 2 |
综合上面所述,只要UART、JTAG、SWD这些硬件通信协议能保证电气连接的规范性和稳定性,那么ISP、IAP就能对芯片正确地编程。
-----------------------------------------------------------------------------------------------------------------
二、烧录方式详述
1、ISP:In System Programming
利用单片机的串行口接到计算机的RS232口,通过专门设计的固件程序来编程内部存储器。芯片可以在目标板上,不用取出来,设计目标板的时候将接口设计在上面。所以叫"在系统编程",即不用脱离系统。程序升级需要现场解决,但不必拆机器。比如:利用STC-ISP对STC芯片编程,如图2.1.1,祥见“STC_ISP下载软件问题汇总与解决”;利用mcuisp或FlyMcu对STM32编程,如图2.1.2所示。
图2.1.1
图2.1.2
-----------------------------------------------------------
2、IAP:In Applicatin Programming( CAN总线实现stm32的IAP )
IAP的实现一般需要很少的外部电路辅助实现,由芯片自身(或外围的芯片)通过一系列操作将代码写入。从结构上将Flash存储器映射为两个存储体,当运行一个存储体上的用户程序时,可对另一个存储体重新编程,之后将控制从一个存储体转向另一个。比如STM32微处理器通过SEGGER J-Flash下载程序,祥见“J-Link使用汇总(STM32F103)”。
图2.2.1
MCU内部都是首先执行一段独立的Boot代码(这段Boot代码一般是出厂预置,或使用编程器烧录,通常只有1k或4k,SST通常是占用一块独立的Block,Philips通常是让BootROM地址与其他Flash重叠,以达到隐藏的效果),Boot负责控制擦除程序存储器及给程序存储器编程的代码(或是处理器外部提供的执行代码),然后通过某种与PC计算机的通信方式(如ethernet网口),将用户指定的某个在PC上编译完成的MCU可运行的二进制代码文件编程入MCU内的程序存储器。
--------------------------------
ISP和IAP最大的不同是:由谁来触发进入BootROM。
ISP有4种触发方式:
1)由外部硬件电路:如VDD保持高电平,给RST连续3个脉冲;
2)检测状态位:如ISPEN,为0时PC指针从0000H开始执行;为1时,通过“引导向量”计算出“ISP代码”的位置。每次复位后都会检测该状态位;
3)中止控制符信号触发芯片复位:中止控制符信号就是指在异步串行口的接收脚上出现长 达一帧长度的低电平,这里一帧的长度与异步串行口的工作模式有关。
4)直接调用ISP:用户程序也可以调用,但是很危险。
--------------------------------
4种方式的目的相同,即进入ISP子程序。比如Philips出厂的ISP子程序在1E00H-1FFFH,只要能引导PC指针指向1E00H就可以了。进入ISP代码的目的是进入BootROM。
IAP的触发简单一些,没有外部触发。通过一些指示位(SST为SC0/SC1、SFCF[1,0];Philips为一段IAP子程序,保存在FF00H~FFFFH地址空间中),达到引导至BootROM的目的。
殊途同归,ISP、IAP所进入的BootROM里面驻留的Boot代码,才是最终目标。
--------------------------------
举例说明:CAN总线实现stm32的IAP
使用stm32f105rct6的can通信做IAP,实现固件的远程更新功能。IAP的实现包括两个程序:BootLoader和应用程序。启动过程先启动BootLoader,等待1s,若接收到烧写指令则开始更新程序,若无指令则启动应用程序。应用程序接收到更新指令后,切换到BootLoader。
远程程序更新需要防止更新失败后,程序卡死,只能通过人工现场更新的情况。可以使用看门狗实现重启返回BootLoader,给重新烧写留出时间。
实现IAP流程,需要的工作包括:
(1)规划单片机存储区,设置中断向量位置,生成应用程序bin文件
(2)编写BootLoader,实现应用程序切换
(3)编写远程更新上位机,实现通信协议
(4)插入看门狗程序,实现烧写失败后重启
使用stm32f105rct6的can通信做IAP,实现固件的远程更新功能。IAP的实现包括两个程序:BootLoader和应用程序。启动过程先启动BootLoader,等待1s,若接收到烧写指令则开始更新程序,若无指令则启动应用程序。应用程序接收到更新指令后,切换到BootLoader。
远程程序更新需要防止更新失败后,程序卡死,只能通过人工现场更新的情况。可以使用看门狗实现重启返回BootLoader,给重新烧写留出时间。
实现IAP流程,需要的工作包括:
(1)规划单片机存储区,设置中断向量位置,生成应用程序bin文件
(2)编写BootLoader,实现应用程序切换
(3)编写远程更新上位机,实现通信协议
(4)插入看门狗程序,实现烧写失败后重启
-----------------
1)规划单片机存储区,设置中断向量位置,生成应用程序bin文件
stm32f105rct6的flash共256KB,规划flash空间:
0x08000000~0x08004000 共16KB空间,给BootLoader
0x08004000~0x08010000 共48KB空间,给应用程序
0x08010000~0x08014000 共16KB空间,保留
0x08014000~0x08018000 共16KB空间,给配置
单片机应用程序在起始地址中的结构,首先是中断向量,然后是代码。
中断向量的结构:开头4字节堆栈指针,接下来是4字节reset函数地址,之后是其他中断函数的地址。
单片机开机后,从0x08000000处取得SP,然后从0x08000004处取得reset地址作为PC,在reset函数中调用main函数,进入C语言控制的程序中。
在keil中的options -> target -> IROM 填写应用程序的起始和长度,并在linker -> use memory layout from target dialog中打钩
在应用程序中,调用NVIC函数,设置中断向量位置为0x08004000
生成应用程序的bin文件:
keil中,在options -> user -> after build -> run 中输入指令
fromelf.exe --bin -o ..\w01sim\bin\mcubin\canext.bin .\obj\test.axf
1)规划单片机存储区,设置中断向量位置,生成应用程序bin文件
stm32f105rct6的flash共256KB,规划flash空间:
0x08000000~0x08004000 共16KB空间,给BootLoader
0x08004000~0x08010000 共48KB空间,给应用程序
0x08010000~0x08014000 共16KB空间,保留
0x08014000~0x08018000 共16KB空间,给配置
单片机应用程序在起始地址中的结构,首先是中断向量,然后是代码。
中断向量的结构:开头4字节堆栈指针,接下来是4字节reset函数地址,之后是其他中断函数的地址。
单片机开机后,从0x08000000处取得SP,然后从0x08000004处取得reset地址作为PC,在reset函数中调用main函数,进入C语言控制的程序中。
在keil中的options -> target -> IROM 填写应用程序的起始和长度,并在linker -> use memory layout from target dialog中打钩
在应用程序中,调用NVIC函数,设置中断向量位置为0x08004000
生成应用程序的bin文件:
keil中,在options -> user -> after build -> run 中输入指令
fromelf.exe --bin -o ..\w01sim\bin\mcubin\canext.bin .\obj\test.axf
-----------------
2)编写BootLoader,实现应用程序切换
建立一个普通的stm32工程,实现can通信和数据协议、flash烧写等功能,当超时无指令,或烧写成功后,需要进行程序切换。
程序切换时,首先应关闭设备时钟、关闭中断,避免应用程序中未对设备进行初始化,导致boot方式启动与冷启动有功能差别。
切换原理:模拟单片机上电过程,人工设置堆栈指针,调用应用程序入口函数。
切换代码如下:
建立一个普通的stm32工程,实现can通信和数据协议、flash烧写等功能,当超时无指令,或烧写成功后,需要进行程序切换。
程序切换时,首先应关闭设备时钟、关闭中断,避免应用程序中未对设备进行初始化,导致boot方式启动与冷启动有功能差别。
切换原理:模拟单片机上电过程,人工设置堆栈指针,调用应用程序入口函数。
切换代码如下:
void switch_2_addr(u32 *pc) //切换到指定的程序指针
{u32 i = 0;RCC->APB1RSTR = 0x00000000;//复位结束RCC->APB2RSTR = 0x00000000;RCC->AHBENR = 0x00000014; //睡眠模式闪存和SRAM时钟使能.其他关闭.RCC->APB2ENR = 0x00000000; //外设时钟关闭.RCC->APB1ENR = 0x00000000;RCC->CR |= 0x00000001; //使能内部高速时钟HSIONRCC->CFGR &= 0xF8FF0000; //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0]RCC->CR &= 0xFEF6FFFF; //复位HSEON,CSSON,PLLONRCC->CR &= 0xFFFBFFFF; //复位HSEBYPRCC->CFGR &= 0xFF80FFFF; //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRERCC->CIR = 0x00000000; //关闭所有中断NVIC->ICER[0] = 0xFFFFFFFF;NVIC->ICER[1] = 0x000007FF;NVIC->ICPR[0] = 0xFFFFFFFF;NVIC->ICPR[1] = 0x000007FF;for(i = 0; i < 0x0B; i++){NVIC->IP[i] = 0x00000000;}__ASM volatile("cpsid i"); //关闭所有中断MSR_MSP(*pc); //堆栈指针是应用程序起始的第一个u32((void (*)(void))*(pc+1))();//入口函数是应用程序起始的第二个u32
}
其中MSR_MSP函数如下:
__asm void MSR_MSP(u32 addr)
{MSR MSP, r0 //set Main Stack valueBX r14
}
-----------------
3)编写远程更新上位机,实现通信协议
上位机实现通信协议:
每个程序具有自己的version,16bit,高1字节为程序代号,低1字节为程序发布版本
通信的过程:
(1)控制方发送查询指令,应用程序或BootLoader收到后发送自身version
(2)控制方发送起始指令,指令中带有长度和crc,应用程序收到后,若不准许,则发不准更新包,若准许,则不响应,直接切入BootLoader
(3)控制方持续发送起始指令,BootLoader收到后,回复相同canid的包,准许更新
(4)控制方得到准许后,发送id递增的can包,将bin文件下载到MCU
(5)发送完成后,控制方额外发送一个can id低16bit为0xffff的包,内容任意,表示结束。BootLoader收到后开始计算crc,若失败,则发失败包。若成功,则开始烧写flash,若烧写失败,发送烧写失败包。
(6)烧写成功,BootLoader切换到应用程序,此时控制方一直发查询指令,直到应用程序回复版本号正确。
上位机实现通信协议:
每个程序具有自己的version,16bit,高1字节为程序代号,低1字节为程序发布版本
通信的过程:
(1)控制方发送查询指令,应用程序或BootLoader收到后发送自身version
(2)控制方发送起始指令,指令中带有长度和crc,应用程序收到后,若不准许,则发不准更新包,若准许,则不响应,直接切入BootLoader
(3)控制方持续发送起始指令,BootLoader收到后,回复相同canid的包,准许更新
(4)控制方得到准许后,发送id递增的can包,将bin文件下载到MCU
(5)发送完成后,控制方额外发送一个can id低16bit为0xffff的包,内容任意,表示结束。BootLoader收到后开始计算crc,若失败,则发失败包。若成功,则开始烧写flash,若烧写失败,发送烧写失败包。
(6)烧写成功,BootLoader切换到应用程序,此时控制方一直发查询指令,直到应用程序回复版本号正确。
-----------------
4)插入看门狗程序,实现烧写失败后重启
在BootLoader中开看门狗,切换到应用程序后喂狗。若程序烧写失败,则切换到应用程序后程序卡死,导致MCU重启,又进入BootLoader,停留1s,等待下次烧写。
4)插入看门狗程序,实现烧写失败后重启
在BootLoader中开看门狗,切换到应用程序后喂狗。若程序烧写失败,则切换到应用程序后程序卡死,导致MCU重启,又进入BootLoader,停留1s,等待下次烧写。
-----------------------------------------------------------
3、ICP:In Circuit Programing
1)MCU只要处于上电状态即可,不必预烧任何代码进MCU。
2)烧录范围涵盖整颗MCU,包括 APROM、DataFlash、CONFIG、LDROM和 ROMMAP。
3)芯片在LOCK的状态下,无法只更新某一区块,只能在erase-ALL之后,更新某一区块,再逐一烧回其它区块;
因为ICP的本质就是走串行接口的Writer Mode,芯片被LOCK之后,除了erase-ALL,所有烧录动作皆会被禁止。
4)因为烧录纯粹是ICP硬件的行为,MCU无法自己更新自己,所以给系统设计者的弹性较小。例如无法藉由ICP去实现IAP的功能。
5)需要其他硬件支持(如NU-LINK等)
6)不严格来说,ISP和IAP也属于在电路编程。
-----------------------------------------------------------------------------------------------------------------
三、相关总结
1、形象点的描述
ISP是把房子拆了再重造一间,但是地基保留,那么在造好之前当然是不能住人。
IAP是在造好的房子里边进行一些装修,当然人可以继续住。
ICP是对房子地基与房子的整体重构。
-----------------------------------------------------------
2、STM32进入BootROM的方式
详细的说明参阅“STM32单片机1之二、STM32_启动模式配置说明“。
-----------------------------------------------------------
3、STM32自动ISP、RS232通信
1)自动ISP原理
当烧录程序时,我们希望BOOT0=1,BOOT1=0。当烧录完成后希望BOOT0=0,BOOT1=0。这里只需考虑BOOT0的高低。查看STM32的参考手册,如下图。
图3.3.1
-----------------
综上所述可以得到:
(1)系统上电,BOOT0需为L,进入模式一。上电复位后,在SYSCLK的第4个上升沿,BOOT引脚的值将被锁存,进入主闪存存储器,执行我们烧录的代码。
(2)烧录HEX文件时,BOOT0需为H,进入模式二。系统必须复位一次(系统上电后默认执行代码,即模式一),让系统重新锁存BOOT引脚。系统进入模式二,开始烧录HEX文件。
(3)程序下载完毕后,若设置了“编程后执行”,系统再次进入模式一,STM32会再次被复位,此时DTR#引脚为高,RTS#引脚为低,STM32复位后,DTR#引脚设置为低,RTS#引脚设置为高,那么Q2和Q3都不导通,此时,STM32重新开始启动后,检测到BOOT0为0,在烧录完成后会有报告:“成功从08000000开始运行”,程序开始正常运行。
图3.3.2
-----------------
图3.3.3的电路可实现自动ISP、串口通信、USB供电三种功能。
图3.3.3 成熟电路
串口下载软件可选用FlyMcu或mcuisp,通过串口的DTR和RTS信号来自动配置BOOT0和RESET信号,不需要用户手动切换它们的状态,直接串口软件自动控制,可以方便的实现一键程序烧录,这里我称之为自动ISP。
CH340G上电后DTR#和RTS#都为高电平,在用FlyMcu烧写软件时,软件下方选择“DTR的低电平复位,RTS高电平进BootLoader”。
图3.3.4
-----------------
CH340G在实际操作时引脚的变化为“DTR#拉高(软件DTR低电平),RTS#拉低(软件RTS高电平)”,即软件设置和实际情况相反。 画个时序图,直观一些。
图3.3.5
-----------------
首先,FlyMcu软件控制DTR输出低电平,则DTR#引脚输出高, 然后RTS置高,则RTS#引脚输出低,这样Q3导通,BOOT0被拉高,即实现设置BOOT0为1,同时Q2也会导通,STM32的复位脚被拉低,实现复位。
延时100ms后,FlyMcu软件控制DTR为高电平,则DTR#引脚输出低电平,RTS维持高电平,则RTS#引脚继续为低电平,此时STM32的复位引脚,由于Q2不再导通,变为高电平,STM32结束复位,但是BOOT0还是维持为1,从而进入ISP模式,接着FlyMcu就可以开始连接STM32下载代码,从而实现自动ISP。
--------------------------------
2)注意事项
(1)CH340在刚上电,稳定需要几秒钟时间,在此期间,DTR引脚会有两次或三次变低的情况,这样会引起单片机上电后复位
两三次,稳定后不会影响程序运行。若不想让单片机上电复位好几次,上电的时候把DTR与RESET断开即可。
(2)PLC通过485线控制变频器调速,电脑用USB转串口连接PLC。用CH340的话,变频器一旦启动,电脑端和PLC的通讯很容易中断,用FT232则无此问题。个人认为稳定性:FT232>PL2303>CH340,这也反映在价格上。
(3)国产类STM32单片机,本人测试过北京兆易创新GD32F103VET6、珠海艾派克APM32F103VCT6、重庆雅特力AT32F403AVGT7,使用FlyMcu软件,mcuisp软件会产生各种不适。
-----------------------------------------------------------------------------------------------------------------
附录1、STM32加密烧录
移步:https://blog.csdn.net/liht_1634/article/details/124673747。
-----------------------------------------------------------------------------------------------------------------