关于STM32 IAP升级之为什么APP执行要&0x2FFE0000这个数值的原因
![嵌入式软件开发](https://pica.zhimg.com/v2-a22fc010e6788d9bdbc613ee09b78c3c_l.jpg?source=172ae18b)
如下图所示,这是我目前用的一款CPU:STM32F446RET6,大小是512KB
![](https://pic3.zhimg.com/80/v2-7568aa425b913c3f9b67b42d434bafbe_720w.webp)
![](https://pic4.zhimg.com/80/v2-805a2880e8278a20e7b63841a63a0c43_720w.webp)
我的bootloader编译完以后占用了26KB的FLASH内存。 我的APP占用了363K的FLASH内存,主要是因为LCD显示,刷的图片很多,很占内存。 为了给以后的Bootloader扩展更多的功能需求,我给我的Bootloader栈顶占用FLASH 0x10000的大小,也就是64k。 所以,目前Bootloader占用了从Sector0-Sector3三个扇区,剩下的区域就分给APP吧。
![](https://pic3.zhimg.com/80/v2-3632998a15ba432a9335bd8497a47b4a_720w.webp)
APP从FLASH的0x8010000开始运行,也就是从扇区4Sector-4开始,STM32F446RET6的FLASH的大小是512KB,由于Bootloader占用了64KB,所以还剩余448KB,这一部分给我的APP用。我们可以将448KB * 1024 => 458752B =>再换算成十六进制>0x70000,所以上面这个0x70000是这么得出来的。 再来看看我的这款CPU的SRAM,先简单了解下SRAM:
![](https://pic4.zhimg.com/80/v2-deaac2f292f487f111c699429f17778f_720w.webp)
然后打开Keil以及芯片数据手册查看。
![](https://pic3.zhimg.com/80/v2-9cf7b82802fafe779454321ca1edbc6e_720w.webp)
从下面文档看出,我的这款CPU的SRAM是0x20000,也就是128KB
![](https://pic4.zhimg.com/80/v2-88e8b3d66d5098e2194e9cb9d127882f_720w.webp)
在写针对DFU固件更新程序时候,这里有一段跳转到APP的代码:
#define USBD_DFU_APP_DEFAULT_ADD 0x08010000U
static void JumpToApp(void)
{
//如果按键没有按下,则启动APP
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 1)
{
/* Test if user code is programmed starting from USBD_DFU_APP_DEFAULT_ADD * address */
if(((*(__IO uint32_t*)USBD_DFU_APP_DEFAULT_ADD) & 0x2FFE0000 ) == 0x20000000)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t *) (USBD_DFU_APP_DEFAULT_ADD + 4);
JumpToApplication = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP((*(__IO uint32_t *) USBD_DFU_APP_DEFAULT_ADD));
JumpToApplication();
}
}
}
我之前一直没搞明白为什么对APP的地址简引用,然后得出的数值 & 0x2FFE0000等于0x20000000就认为有APP,可以跳转到对应的地址去执行我的APP程序了,那我&上别的什么乱七八糟的数据它不香吗??为何呢??
原因如下:
程序在运行过程中,0x20000000是我们SRAM运行的起始地址,空间是128KB,也就是0x20000000-0X2001FFFF这个范围。 所以*(__IO uint32_t*)USBD_DFU_APP_DEFAULT_ADD) ,这句话的意思是取得用户地址空间存放的数据,这个空间就是0x08010000,当APP运行的程序栈顶指针落在SRAM区域时,也就是0x20000000到0X2001FFFF这个区间时候,这个时候即是有效的栈顶指针,由于开始的地址是0x20000000,而结束的地址是0X2001FFFF,我们只要判断它的高16位,即是确定这个地址范围在从0x2000开始。
![](https://pic3.zhimg.com/80/v2-4a1b6d485e93281bade82744eaa42932_720w.webp)