总结STM32 IAP 串口升级

总结下STM32 IAP串口升级

IAP升级时,在STM Flash中会包含两个程序:IAP和APP,IAP负责,如果有要升级的APP,则将该APP替换旧APP,并运行新APP,如果没有要升级APP,则立即运行现有的APP程序。

关键明白如下:

1. 需要在FLASH内部,分段去存IAP和APP。在keil中,可以通过配置IROM去配置。

如APP存在0x8004000,size是0xC000空间大小的flash中。

IAP存储在0x8000000,size是0x4000存储空间上

2. IAP中通过修改SP和PC的值来,让程序通过IAP跳转到APP来执行。

SP的值存放在哪里呢?我们通过map来看

APP.map看到sp的值是:0x20001568,而app.bin中看到首4个字节,存放的就是该值。

APP的bin值

所以我们设置SP就是调用__set_MSP(*(uint32_t*)(DEVICE_APP_ADDR)); // APP的首四个字节,从APP存放到flash的首地址上取值。

PC怎么设置呢?我们看到PC指针是执行到DEVICE_APP_ADDR+4上了,这里存放的是什么呢?我们从app.map中再来查看下

Reset_Handler存放的地址是:0x08004101,而DEVICE_APP_ADDR+4刚好就是该地址,说明PC指针执行到了Reset_Hander函数了。

Reset_Hander就是做什么呢?我们在*.s启动文件中可以看到,执行了SystemInit函数,然后就到了我们的main函数了。所以在IAP中通过设定SP和PC,让程序切换到了APP的栈和main函数中来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// IAP flash     16K
#define DEVICE_IAP_ADDR                    (FLASH_BASE)  
#define DEVICE_IAP_SIZE                    (16*1024)

// APP flash  16K
#define DEVICE_APP_ADDR (DEVICE_IAP_ADDR+DEVICE_IAP_SIZE)
#define DEVICE_APP_SIZE (16*1024)

if(((*(uint32_t*)DEVICE_APP_ADDR) & 0x2FFE0000) == 0x20000000)
{
    g_jump_to_application  = (func_ptr)(*(uint32_t*) (DEVICE_APP_ADDR + 4));
    __set_MSP(*(uint32_t*)(DEVICE_APP_ADDR));
    g_jump_to_application();
}

3.需要在APP重新去设定中断表的地址。

原因是:IAP中有中断表,APP中也有中断表,如果我们在APP中,不去重新设定中断表地址,那么APP中的中断函数,就无法去执行到。

1
2
3
4
5
6
    /* close interruption*/
    __set_FAULTMASK(1);
    /* set vector table */
    SCB->VTOR = FLASH_BASE | 0x4000;
    /* open interruption*/
    __set_FAULTMASK(0);

把我这次的例程及文件整理成文档,保存到城通网盘,需要话,可以到该链接下下载。

https://t00y.com/dir/25372526-38549933-fb6a6d