1、理论
这个比前面SRAM启动更为简单。
我下面用到的芯片是STM32F411RET
流程:
1、在bootlooder程序中往FLSH APP区写入需要更新的代码。我这里用到的是0x08020000 .
2、关闭所有中断
3、跳转到FLSH APP区
2、KEIL中的设置
bootloader:实际上下面就是默认值
app:
默认的条件下,图中 IROM1 的起始地址(Start)一般为 0X08000000,大小(Size)为 0X80000,
即从 0X08000000 开始的 512K 空间为我们的程序存储区。而图中,我们设置起始地址(Start)
为 0X08020000,即偏移量为 0X20000(128K 字节),因而,留给 APP 用的 FLASH 空间(Size)
只有 0X80000-0X20000=0X6000(384K 字节)大小了。设置好 Start 和 Szie,就完成 APP 程
序的起始地址设置。
向量重新定义:
3、代码
实现的功能:通过SD卡给主板升级
跳转函数
iap_write_appbin(FLASH_APP1_ADDR);//
u8 iap_write_appbin(u32 appxaddr)//(u32 appxaddr,u8 *appbuf,u32 appsize)
{
u32 t;
u16 i=0;
u32 temp;
// u8 appflagstart = 0;
u32 fwaddr=appxaddr;//当前写入的地址
u32 iapbuf[512]; //2K字节缓存
u8 abuff[2048] = {0};
FRESULT res;
u32 br = 0;
f_open(&SDFile, MasterUpdata_filename, FA_READ);
while(1)
{
for(i = 0; i < 4; i++)
{
res = f_read(&SDFile, abuff+512*i, 512, &br);
}
// if(appflagstart ==0)
// {
// appflagstart = 1;
// if((abuff[0x400] != apptype[0])&&(abuff[0x401] != apptype[1])&&(abuff[0x402] != apptype[2])&&(abuff[0x403] != apptype[3]))
// {
// LCD_ShowString(60,150,300,32,32,"APP ERROR ");//
// return 0;
// }
// }
for(t=0;t<2048;t+=4)
{
temp=(u32)abuff[3+t]<<24;
temp|=(u32)abuff[2+t]<<16;
temp|=(u32)abuff[1+t]<<8;
temp|=(u32)abuff[0+t];
iapbuf[t/4]=temp;
}
STMFLASH_Write(fwaddr,iapbuf,512);
fwaddr+=2048;//偏移2048 512*4=2048
if ((res!=FR_OK) || br == 0)
{
break;
}
memset(abuff,0,2048);
}
f_close(&SDFile);
// mf_unlink((u8 *)MasterUpdata_filename);
return 1;
}
跳转函数:
iap_load_app(FLASH_APP1_ADDR);//jamp to main
void iap_load_app(u32 appxaddr)
{
typedef void (*_func)(void);
__disable_irq();
/* MCU peripherals re-initial. */
{
// GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
// __HAL_RCC_GPIOA_CLK_ENABLE();
// __HAL_RCC_GPIOB_CLK_ENABLE();
// __HAL_RCC_GPIOC_CLK_ENABLE();
// __HAL_RCC_GPIOD_CLK_ENABLE();
// __HAL_RCC_GPIOE_CLK_ENABLE();
// __HAL_RCC_GPIOH_CLK_ENABLE();
// GPIO_InitStruct.Mode = GPIO_Mode_IN;
// GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
// GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
// GPIO_InitStruct.Pull = GPIO_NOPULL;
// GPIO_InitStruct.Pin = GPIO_PIN_All;
// GPIO_InitStruct.Pin &= ~(GPIO_PIN_13 | GPIO_PIN_14); /* SWDIO/SWCLK */
// HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// GPIO_InitStruct.Pin = GPIO_PIN_All;
// HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
// HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
// HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
// HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
/* reset systick */
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
/* disable all peripherals clock. */
RCC->AHB1ENR = (1<<20); /* 20: F4 CCMDAT ARAMEN. */
RCC->AHB2ENR = 0;
RCC->AHB3ENR = 0;
RCC->APB1ENR = 0;
RCC->APB2ENR = 0;
/* Switch to default cpu clock. */
RCC->CFGR = 0;
} /* MCU peripherals re-initial. */
/* Disable MPU */
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
/* disable and clean up all interrupts. */
{
int i;
for(i = 0; i < 8; i++)
{
/* disable interrupts. */
NVIC->ICER[i] = 0xFFFFFFFF;
/* clean up interrupts flags. */
NVIC->ICPR[i] = 0xFFFFFFFF;
}
}
/* Set new vector table pointer */
SCB->VTOR = appxaddr;
/* reset register values */
__set_BASEPRI(0);
__set_FAULTMASK(0);
/* set up MSP and switch to it */
__set_MSP(*(uint32_t*)appxaddr);
// __set_PSP(*(uint32_t*)appxaddr);
__set_CONTROL(0);
/* ensure what we have done could take effect */
__ISB();
__disable_irq();
/* never return */
((_func)(*(uint32_t*)(appxaddr + 4)))();
}