gcc编译hal库方式实现M0系列芯片IAP
IAP:调用iap_load_app函数即可,输入参数为app起始地址
void iap_load_app(uint32_t appxaddr)
{
uint32_t sram_addr = 0;
sram_addr = (*(__IO uint32_t *)appxaddr) & 0x2FFE0000;
printf("sram_addr : %08lx\n", sram_addr);
//APPLICATION_ADDRESS是在FLASH中存放APP的起始地址
//此判断是为了保证APP的栈地址是在SRAM中。其实结果并不一定是0x20000000。有些APP可能定义的全局变量较多,那么栈的起始地址会偏移
if (((*(__IO uint32_t *)appxaddr) & 0x2FFE0000) == 0x20000000)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t *)(appxaddr + 4);
printf("jump addr : %08lx\n", JumpAddress);
Jump_To_Application = (pFunction)JumpAddress;
/* Initialize user application's Stack Pointer */
MSR_MSP(*(__IO uint32_t *)appxaddr);
printf("appxaddr : %08lx\n", appxaddr);
/*关闭或反初始化前面用到的外设和中断*/
HAL_DeInit();
Jump_To_Application();
}
}
其中MSR_MSP()函数
void MSR_MSP(u32 addr)
{
__ASM volatile("MSR MSP, r0");
__ASM volatile("BX r14");
}
其中JumpAddress定义
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;
APP:
void NVIC_SetVectorTable(void)
{
uint8_t i;
uint32_t *pVecTab = (uint32_t *)(0x20000000);
//复制中断向量表到SRAM首地址
for (i = 0; i < 48; i++)
{
*(pVecTab++) = *(__IO uint32_t *)(APPLICATION_ADDRESS + (i << 2));
}
//开启 SYSCFG 时钟
__HAL_RCC_SYSCFG_CLK_ENABLE();
//重映射 SRAM 地址到 0x00000000
__HAL_SYSCFG_REMAPMEMORY_SRAM();
}
在mian()函数一开始调用NVIC_SetVectorTable()函数
int main(void)
{
/* USER CODE BEGIN 1 */
NVIC_SetVectorTable();
修改.ld文件,例如STM32F070RBTx_FLASH.ld
RAM修改为0x200000C0,flash修改为自己的起始地址
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x200000C0, LENGTH = 16K
FLASH (rx) : ORIGIN = 0x8005000, LENGTH = 100K
}