总结下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