一、IAP原理及过程
二、遇到的问题
1、中断向量表的充定向问题
(1)与M3核的单片机由区别
1)、STM32F0系列没有void NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)这个函数,所以不能像其他系列的那样设置中断向量表;
2)、M0核中需要把APP部分中的中断向量表重定向到SRAM中(在M3中一般是重定向在flash中);
在M3内核中可以通过操作VTOR寄存器来重映射中断向量表
SCB->VTOR = FLASH_BASE | 0x10000;
/* Vector Table Relocation in Internal FLASH. */
在M0内核中需要
memcpy((void*)0x20000000, (void*)IAP_ADDR, 0xB4);
__HAL_SYSCFG_REMAPMEMORY_SRAM();
其中,0x2000 0000是SRAM的起始地址,这个不需要改动。
而之后的两个参数需要根据实际情况作出修改。IAP_ADDR是应用程序的起址地址,从这里开始的VECTOR_SIZE字节,存放是的应用程序的中断向量表。VECTOR_SIZE是指中断向量表的大小,具体多大可以在startup.s文件里计算得到。
3)、跳转
4)、几种中断向量表重定向的方法
A: memcpy((void*)0x20000000, (void*)IAP_ADDR, 0xB4);
B:
void InterruptRemap(void)
{
uint8_t i;
u32_t Data;
u32_t Address;
for(i=1;i<48;i++)
{
Data = *(__IO uint32_t *)(0x08003000+i*4);
Address = 0x20000000 + (i*4);
*(__IO uint32_t *)Address= (uint32_t )Data;
}
__HAL_SYSCFG_REMAPMEMORY_SRAM();
}
三、FLASH和SRAM的配置
1、BootLoader部分
2、app部分
ROM的设定值要与程序中分配的空间地址对应,例如程序中的地址分配如下:
/*< Bootloader address base. 12KB>*/
/* bootloader: 12KB 0x08000000--0x08003000 */
#define BOOTLOADER_ADDR_BASE 0x08000000
/*< APP address base. 24KB >*/
/* 0x08003000--0x08009000 */
#define APP_START_ADDR 0x08003000
/*< Parameter address base. 2KB. >*/
#define PARAM_ADDR_BASE 0x08009000
#define UPDATE_FLAG_L8_ADDR (PARAM_ADDR_BASE+0)
#define UPDATE_FLAG_H8_ADDR (PARAM_ADDR_BASE+1)
#define APP_SIZE_L8_ADDR (PARAM_ADDR_BASE+2)
#define APP_SIZE_M1_ADDR (PARAM_ADDR_BASE+3)
#define APP_SIZE_M2_ADDR (PARAM_ADDR_BASE+4)
#define APP_SIZE_H8_ADDR (PARAM_ADDR_BASE+5)
#define APP_CRC_L8_ADDR (PARAM_ADDR_BASE+6)
#define APP_CRC_H8_ADDR (PARAM_ADDR_BASE+7)
/*< APP TEMP address base. 24KB >*/
#define APP_TEMP_START_ADDR 0x08009800
/*< Deserve address base. 2KB >*/
#define DESERVE_ADDR_START 0x0800F800
设定APP部分的SRAM,要注意剩余长度的计算,剩余长度=SRAM总长度 - 中断向量表所用长度 - 1:
四、待解决的问题
发现flash不能字读取(或是要字节对齐,起始地址要是4的倍数),这个问题还没有找到原因,可能是我字读取函数写的有问题。
/* Get the new app size. */
//newAPPSize = hal_flash_read_word(APP_SIZE_L8_ADDR);//直接读取字,不成功
newAPPSizeL = hal_flash_read_half_word(APP_SIZE_L8_ADDR);
newAPPSizeH = hal_flash_read_half_word(APP_SIZE_M2_ADDR);
newAPPSize = (newAPPSizeH<<16) | newAPPSizeL;
u32_t hal_flash_read_word(u32_t addr)
{
return *(__IO u32_t *)addr;
}