IAP方案

把代码区分成了两部分:
1.bootloader(启动加载代码区)
2.user application(用户应用代码区)
程序执行初始化进入bootloader,在bootloader里面检测条件是否被触发(可通过按键是否被按下,串口是否接收有特定的数据、U盘是否插入等)信号,如果有则对user application代码区进行擦除合重新写入新的用户代码的操作;如果没有,就直接跳转到user application执行应用;

正常STM32F103ZET6的启动有三种方式:
1.内置Flash启动;
2.内置SRAM启动;
3.系统存储器ROM启动;
通过BOOT0合BOOT1引脚的设置可以选择哪种启动方式。

对于Flash启动而言,Flash的地址:0x08000000 - 0x0807ffff,一共512KB。这里首要的是中断问题。正常中断过程为:发生中断请求,到中断向量表中查找中断函数入口地址,跳转到中断函数内,执行中断函数逻辑,然后返回。即说明了STM32有一个中断向量表用来存放各个中断服务函数的入口地址,内置的Flash分配情况如下:
栈顶地址 | 中断向量表 | 中断服务函数 | 主程序

0x08000000
(从0x08000000地址开始,借用网友的一张图片)
STM32F10X 应用固件升级-LMLPHP
这个中断向量表存放在代码开始的后4个字节处,即0x08000004地址。代码开始的4个地址是存放堆栈栈顶的地址,当发生中断后程序通过查询该表得到响应的中断服务程序入口地址,然后再跳转到相应的中断服务程序中执行。上电后从0x08000004处取出复位中断向量的地址,然后跳转到复位程序的入口,执行结束后,跳转到main函数中。从中断向量表中找到相应的中断函数入口地址,跳转到相应的中断服务函数,执行完中断函数后,再返回到main函数中去,这就是整个启动过程。

若使用IAP方案,则内置的Flash分配情况大致如下:
STM32F10X 应用固件升级-LMLPHP
在内置的Flash里面添加了一个bootloader程序,Bootloader程序和user application各有一个中断向量表,假设Bootloader程序占用的空间为N+M字节,则程序按照如下方式进行运行:
STM32F10X 应用固件升级-LMLPHP

上电初始化程序还是从0x08000004地址处开始,取出中断复位向量地址,执行复位中断函数后,跳转到IAP的main中。在IAP的main函数执行完成后,强制跳转到0x08000004 + N + M地址处,在跳转到user application代码区的中断复位向量地址,当发生中断复位请求后,程序跳转到新的中断向量表中,再跳转到中断函数去执行,完成后再跳转到user application的main函数中。

当CPU产生一个中断请求时,对于user application处的中断函数,是怎样进来的呢?
在main函数的执行过程中,如果CPU得到了一个中断请求,PC指针本来应该跳转到0x08000004处的中断向量表中,但是由于我们设置了中断向量偏移量N+M,所以使得PC指针被强制跳转到0x08000004 + N + M处的中断向量表中的地址,执行对应的user application中的中断服务函数,执行结束后返回到user applicaiton main函数中去。

IAP过程描述:

1、IAP的bootloader引导程序。
对于片内Flash得至少分成2个分区,对应至少两个完整的程序;
低地址分区放入IAP程序(bootloader引导程序);告抵制分区烧写APP固件。

IAP程序中,当满足跳转条件(通过串口,网络等方式,告知IAP程序可以进行升级)时,执行跳转到user application的应用程序,跳转代码流程:
需要设定跳转目的地的APP应用程序栈顶地址指针:
__set_MSP(*(__IO uint32_t *) USER_FLASH_START_PAGE_ADDRESS);
其中:
#define USER_FLASH_START_PAGE_ADDRESS 0x08009000 — 分配36K空间

2、user application应用程序
需要配置修改,Target的IROM1的起始地址:
STM32F10X 应用固件升级-LMLPHP

还有中断向量表偏移:
#define _ IAP__ (1)
int main(void)
{
#ifdef _ IAP__
NVIC_SetVectorTable(NVIC_VectTab_FLASH, VectorTable_Offset);
#endif
}

其中:
#define NVIC_VectTab_FLASH ((uint32_t)0x08000000UL)
#define VectorTable_Offset((uint32_t)0x9000UL)

3、查找错误:

如果做了上边的工作,IAP依然无法顺利执行跳转至app应用程序,可以查看.map和.bin文件,确定是否如实的改变的中断向量表的偏移和栈顶指针,如图:
STM32F10X 应用固件升级-LMLPHP
.bin文件:
STM32F10X 应用固件升级-LMLPHP
可以看到,主栈顶MSP地址=0x2000C8C8、reset_handler地址=0x08009189
如此,才能生效,否则,可能原因:
修改后的向量表偏移,在之后的程序中,又再次被还原,通过如下的函数:

  • void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
  • void SystemInit (void);
  • SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;123

附:

1、如需要.hex文件转.bin,参见上边的文章
当然,就算使用.hex文件,同样可以升级,只是需要修改IAP中判定已经升级的文件是否有效,文件条件部分的代码:
if((((__IO uint32_t)USER_FLASH_FIRST_PAGE_ADDRESS) & 0x2FFE0000 ) == 0x20000000)

2、地址偏移后的app应用程序,是否能够独立的运行?
不能,理由:
STM32F10X 应用固件升级-LMLPHP
可上知,开机上电并不能够找到我们指定的偏移后的向量表

10-06 14:56