STM32的IAP升级APP

STM32的IAP升级APP

什么是IAP?
In Application Programming的首字母缩写,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。 通常在用户需要实现IAP功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信管道(如USB、USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。这两部分项目代码都同时烧录在User Flash中,当芯片上电后,首先是第一个项目代码开始运行,它作如下操作:
1)检查是否需要对第二部分代码进行更新
2)如果不需要更新则转到4)
3)执行更新操作
4)跳转到第二部分代码执行
​ 第一部分代码必须通过其它手段,如JTAG或ISP烧入;第二部分代码可以使用第一部分代码IAP功能烧入,也可以和第一部分代码一道烧入,以后需要程序更新是再通过第一部分IAP代码更新。
​ 对于STM32来说,因为它的中断向量表位于程序存储器的最低地址区,为了使第一部分代码能够正确地响应中断,通常会安排第一部分代码处于Flash的开始区域,而第二部分代码紧随其后。
​ 在第二部分代码开始执行时,首先需要把CPU的中断向量表映像到自己的向量表,然后再执行其他的操作。
​ 如果IAP程序被破坏,产品必须返厂才能重新烧写程序,这是很麻烦并且非常耗费时间和金钱的。针对这样的需求,STM32在对Flash区域实行读保护的同时,自动地对用户Flash区的开始4页设置为写保护,这样可以有效地保证IAP程序(第一部分代码)区域不会被意外地破坏。
IAP与ISP的区别
在线编程目前有两种实现方法:在系统编程(ISP)和在应用编程(IAP)。ISP一般是通过单片机专用的串行编程接口对单片机内部的Flash存储器进行编程,而IAP技术是从结构上将Flash存储器映射为两个存储体,当运行一个存储体上的用户程序时,可对另一个存储体重新编程,之后将控制从一个存储体转向另一个。ISP的实现一般需要很少的外部电路辅助实现,而IAP的实现更加灵活,通常可利用单片机的串行口接到计算机的RS232口,通过专门设计的固件程序来编程内部存储器。
IAP跳转到APP需要中断重映射
Stm32f0系列MCU中断矢量表的定位跟STM32其它系列相比有点差异,即M0系列没有像其它M3/M4/M0+系列所具备的中断矢量表重定位寄存器,其中断矢量表不能借助矢量重定位寄存器简单修改实现。所以Stm32f0 IAP的过程会跟其它系列的STM32芯片的IAP动作有所不同。
​ IAP程序及自身的中断向量表放在内部FLASH的低端地址区。对于STM32 MCU而言,就是从0X0800 0000处开始放IAP代码。APP程序代码及自身中断矢量表存放在离0X0800 0000某个地址偏移量【offset】的地方,即从0x0800 0000+offset的地址开始存放APP代码及中断矢量。显然那个【offset】要大于IAP的程序空间。假设这里OFFSET为0x3000,即APP程序的起始地址为0x08003000。为了APP程序能正常相应中断,这里需要做2个步骤:
​ 1、将APP的中断向量表拷贝到SRAM里面去。M0的中断向量表由48个有序字组成,把它们从flash区0x08003000开始的中断向量表拷贝到0x2000 0000的SRAM区。
​ 2、做存储地址的映射,即把SRAM映射到代码执行区的地址0X00处。
大致流程:
在这里插入图片描述
经过上述操作步骤后,当APP里发生中断时,内核就从地址0x00处的向量表取相应中断的入口地址,即相当于从0x2000 0000处的向量表取中断入口地址,当然也相当于从0x08003000处的向量表取中断入口地址,然后去执行相应中断程序。
M0(stm32f030cc)的重映射、系统启动、中断向量表的关系:
重映射:

①MEM_MODE的值在上电后有BOOT0,BOOT1的状态值决定。
②MEM_MODE的值决定了哪个内存映射到地址0x0000 0000
也就是说: 当MEM_MODE =00/10时,Main Flash映射到地址0x0000 0000,即地址0x0800 0000映射到0x0000 0000. 当MEM_MODE =01时,System Flash映射到地址0x0000 0000,也就是芯片自带的Bootloader代码部分会映射到地址0x0000 0000,即0x1FFF C800映射到地址0x0000 0000. 当MEM_MODE =11时,Embeded SRAM映射到地址0x0000 0000,也就是内存地址0x2000 0000映射到地址0x0000 0000.
③经过映射后,系统访问地址0x0000 0000地址,就相当于直接访问映射的地址,如0x0800 0000.
④由BOOT0,BOOT1的状态决定MEM_MODE的值,进而决定哪个地址映射到地址0x0000 0000,这一过程我们称之为映射。默认映射是系统自动完成的,并由BOOT0,BOOT1的状态决定。
⑤MEM_MODE位是RW的,也就是说可以修改的,如果修改其中,也就会相应的修改映射到0x0000 0000的地址,这一修改的过程,我们就叫其为重映射。重映射是通过用户代码通过修改MEM_MODE的值来完成的。

系统启动过程:

①系统复位
②CPU在系统时钟的第4个上升沿根据BOOT0,BOOT1的配置确定寄存器SYSCFG_CFGR1的MEM_MODE的值 。
③MEM_MODE进一步决定哪个地址(Main Flash,System Flash,SRAM)映射到地址0x0000 0000。
④CPU从地址0x0000 0000获取栈顶,从0x0000 0004开始执行代码,也就是从映射地址获取栈顶,从映射地址+4的地方开始执行代码。
⑤映射地址+4对应着复位中断例程(如0x08000 0004),也就是系统一开始就执行Reset_Handler,进而运行SystemInit然后进入到main函数,就这样,整个代码启动完成。

中断与中断向量表:

​ 在Coretext-M3与Coretext-M4核中,在System Control Block中存在一个向量表偏移量寄存器 VTOR(0xE000ED08),系统产生中断后,内核通过这个寄存器的值来找到中断向量表的地址,进而执行中断例程代码,当然,此寄存器的值是可以修改的,它的默认值为0。实际上在大部分的M3和M4的工程中,一般都是在SystemInit函数中对此寄存器的值进行设置,当此之前,它的值为默认值0,由于映射关系,实际上就是指向映射地址,比如0x0800 0000。
​ 但是,由于STM32F0XX采用的是M0核,它是没有这个VTOR寄存器的,那么它又是怎么找到中断向量表的地址的呢?对于M0来说,中断向量表的地址固定在地址0x0000 0000上! 对此,我们也可以这么理解,将M0理解成M3/M4的特殊情况,M0假设也存在VTOR这么一个虚拟寄存器,只不过它的值不能修改,固定为0罢了,而M3/M4的这个VTOR寄存器一开始时它的值也是为默认值0,只不过在程序运行到SystemInit()函数后,在代码中明确对其进行了修改。

调用过程:
-> 产生中断
-> CPU固定到地址0x0000 0000上找中断入口函数,由于映射关系,实际上是在从映射地址上寻找。
-> 找到并执行中断例程

/* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
     /* Jump to user application */
     JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
     JumpToApplication = (pFunction) JumpAddress;
     /* Initialize user application's Stack Pointer */
     __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
     JumpToApplication();
}
如上,首先测试APP地址是否存在用户代码,如果存在,则首先将APPLICATION_ADDRESS + 4,作为跳转地址,然后从APPLICATION_ADDRESS取栈顶并赋值给SP寄存器,最后跳转。
	跳转代码后,PC指针变了,SP栈指针也修改了,但是,中断向量表的位置并没有修正为APP的中断向量表位置,还是采用IAP的中断向量表位置。如果此时系统产生中断,CPU还会固定从0x0000 0000地址中去找中断入口,由于从IAP到APP,内存映射并没有改变,因此,实际上还是从0x0800 0000上去找中断入口,也就是还是在IAP的中断向量表上寻找,继续执行IAP的中断例程,进而引发hard fault,这显然不是我们想要的。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值