芯片IAP升级机制讲解

一、先了解ICP和ISP、IAP之间的区别:
1、 ISP(In System Programing 在系统编程)的实现相对要简单一些,一般通用做法是内部的存储器可以由上位机的软件通过串口来进行改写。对于单片机来讲可以通过SPI或其它的串行接口接收上位机传来的数据并写入存储器中。所以即使我们将芯片焊接在电路板上,只要留出和上位机接口的这个串口,就可以实现芯片内部存储器的改写,而无须再取下芯片。例如,我们开始接触到的STC51单片机的程序下载方式(点击上位机下载----->复位(断电)----->下载)

2、 IAP(In applicatin programming 在应用编程)的实现相对要复杂一些,在实现IAP功能时,单片机内部一定要有两块存储区,一般一块被称为BOOT区,另外一块被称为APP存储区。单片机上电从BOOT区开始运行,如果有外部改写程序的条件满足,则对存储区的程序进行改写操作。如果外部改写程序的条件不满足,程序指针跳到APP存储区,开始执行放在存储区的APP程序,这样便实现了IAP功能。

3、 ICP(In-Circuit Programming 在线编程)通过JTAG/SWD协议或者系统加载程序(Bootloader)下载用户应用程序到微控制器中。这种情况使用仿真器下载或者芯片厂商提供的ICP软件。

总结:(1)(重要!!!)IAP和ISP是我们研发生产中使用的比较多的情况,使用ISP外部条件触发(网上说有四种方式这里不介绍了,感兴趣的可以百度一下),IAP升级完全是芯片内部控制的(这个是很大的优点,试想当你的产品嵌入其他产品内部时候,你不可能打开外壳再外部触发升级。)。

(2)在嵌入式产品生产阶段,往往一些公司使用ICP或ISP的方式将裸芯片烧写IAP+APP程序,烧写的程序是bin文件格式或者加密后的bin文件格式(加密后的bin文件只能使用自己公司的上位机软件进行烧写否则产品无法正常启动)。

(3)在研发阶段,使用的IAP程序是通过JTAG或ISP烧入到芯片,然后通过上位机通过USB,UART或SPI的方式将应用程序(APP)烧写到芯片。

二、了解一下RAM和ROM的区别:
1、 RAM: 随机存储器,可以随时进行读写操作,速度很快,掉电以后数据会丢失。比如内存条、SRAM、SDRAM、DDR 等都是 RAM。RAM 一般用来保存程序数据、中间结果。

2、 ROM:只读存储器,笔者认为目前“只读存储器”这个定义不准确。比如我们买手机,通常会告诉你这个手机是 4+64 或 6+128 配置,说的就是 RAM 为 4GB 或 6GB,ROM 为 64G 或128GB。但是这个 ROM 是 Flash,比如 EMMC 或 UFS 存储器,因为历史原因,很多人还是将Flash 叫做 ROM。但是 EMMC 和 UFS,甚至是 NAND Flash,这些都是可以进行写操作的。

总结:(重要!!!)RAM 速度快,可以直接和 CPU 进行通信,但是掉电以后数据会丢失,容量不容易做大(和同价格的 Flash 相比)。ROM(目前来说,更适合叫做 Flash)速度虽然慢,但是容量大、适合存储数据(ROM程序的存储位置)。

三、IAP升级的机制讲解:
1、先看你STM32的内存地址架构图
在这里插入图片描述
从图上可以看出:
(1)内部flash 是从0x0800 0000开始 到0x0803 FFFF 结束, 0x0803FFFF-0x0800 0000= 0x20000 =256k flash的大小是256k;

(2)SRAM的开始地址是 0x2000 0000 开始到0x2000 FFFF结束,大小为64K
而刚刚说了我们程序是放在ROM中,那IAP(在线升级程序)代码放到Flash Memory里以0x0800 0000 开始的位置(有些RAM内核的芯片的内部flah起始地址是0x00000000)。

2、芯片BOOT脚配置
在这里插入图片描述
因为我们从flash烧写IAP程序,所以一般我们芯片引脚原理图设计为(BOOT0=0/1,BOOT1=0):
在这里插入图片描述
当产品开发完成时候,只能选择IAP升级方式,即:BOOT0=0,BOOT1=0;
三、如何编写IAP程序?
1、程序地址分配图:
在这里插入图片描述
上图是IAP+APP程序的大致结构图,在MDK配置IAP程序的地址空间分布为:
在这里插入图片描述
2、USB方式的IAP升级(UART,SPI等方式都大同小异)
(1)芯片正常执行在APP(应用程序)中(0x08004000-0x08030000)段,当要进行升级时候,上位机或者其他产品发送升级指令,升级指令,我们将会将升级标志位(假如是0xA0A0A0A0)写到flash的0x08003000开始的Flag区(大小为0x1000=4KByte,Flag区是我自己命名的)某个位置,写入标志位后,进行软复位。(写入我们预留的Flag区,可以写入APP文件的大小或者上位机分了多少包)

(2)复位后,程序又从0x00000000地址开始执行即进入IAP程序,这里为啥从0x08000000开始执行可以看我上篇文章STM32的Flash地址是0x08000000,从0x00000000不可以?
https://blog.csdn.net/weixin_42231514/article/details/106178653

(3)进入IAP程序后,我们将读flash的0x08003000起始的Flag区对应的标志位是不是0xA0A0A0A0,如果是,则上位机通过约定好的协议分包发固定字节的APP对应的bin文件或者加密后的bin文件(这里你的上位机会将加密的bin文件解密)写到0x08004000为起始的APP区。

(4)如果最后一包数据不满足约定的固定字节,这种情况下上位机可以填充0来满足固定字节或者IAP程序进行特别处理最后一包写入flash。

(5)IAP程序接收完最后一包APP 程序并写入flash后,此时跳转到0x08004000位置去执行APP程序,在APP程序初始化部分清除Flag区域的标志位0xA0A0A0A0。
下图为APP程序中地址空间的分配:
在这里插入图片描述
需要注意点:(重要!!!
(1) 在IAP程序中:
#define ApplicationAddress 0x08004000
#define NVIC_VectTab_FLASH ((uint32_t)0x08000000)
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0000);

JumpAddress = *(vu32*) (ApplicationAddress + 4);//用户代码区第二个字为程序开始地址(复位地址)		
Jump_To_Application = (pFunction) JumpAddress;
MSR_MSP(*(vu32*)ApplicationAddress);		//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
Jump_To_Application();		//跳转到APP.	

(2)在APP程序中:

 #define NVIC_VectTab_FLASH           ((uint32_t)0x08000000)
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x4000); //APP中,中断向量表的起始地址

如果有什么疑问,欢迎大家留言讨论。

猜你喜欢

转载自blog.csdn.net/weixin_42231514/article/details/106338843
IAP