IAP在线升级可以是芯片更新程序脱离烧录器等专用工具,可以使用串口、网络等外部通用通信方式来达到升级的目的,方便后续程序升级更新。
STM32F0系列是M0内核,与STM32F1和F4系列有一点不一样,因为在F0系列没有中断向量表重映射。即M0系列没有像其它M3/M4/M0+系列所具备的中断矢量表重定位寄存器,其中断矢量表不能借助矢量重定位寄存器简单修改实现。所以STM32f0 IAP的过程会跟其它系列的STM32芯片的IAP动作有所不同。但是stm32有两种启动方式,一种是从flash启动,默认地址为0x0800000,一种是从RAM启动,默认地址为0x20000000,所以可以让IAP从Flash启动,而APP从RAM启动,通过接口SYSCFG_MemoryRemapConfig配置。由于我们是把APP代码直接拷贝到0x0800000+offset的地址上去的,其中断向量表在Flash里面,所以在APP启动的时候,需要把中断向量表拷贝到RAM的起始地址中去。
STM32F030的Reference manual中找到以下说明:
Physicalremap
Once the boot mode is selected, the application software canmodify the memory accessible in the code area.This modification isperformed by programming the MEM_MODE bits in the SYSCFGconfiguration register 1 (SYSCFG_CFGR1). Unlike Cortex? M3 and M4,the M0 CPU does not support the vector table relocation. Forapplication code which is located in a different address than0x0800 0000, some additional code must be added in order to be ableto serve the application interrupts. A solution will be to relocateby software the vector table to the internal SRAM:
? Copy the vector table from the Flash (mapped at the base of theapplication load address) to the base address of the SRAM at 0x20000000.
? Remap SRAM at address 0x0000 0000, using SYSCFG configurationregister 1.
? Then once an interrupt occurs, the Cortex?-M0 processor willfetch the interrupt handler start address from the relocated vectortable in SRAM, then it will jump to execute the interrupt handlerlocated in the Flash.
This operation should be done at the initialization phase of theapplication. Please refer to AN4065 and attached IAP codefrom www.st.com for more details.
Bootlader 源码如下
void HardwareInit(void)
{
/* close all interrupt*/
__disable_irq();
RCC_DeInit();//为了从IAP程序中跳出运行APP程序的时候正常开始,初始化时要RCC为复位状态,恢复NVIC
SystemInit();
extern uint32_t SystemCoreClock;
SysTick_Config(SystemCoreClock/600);
Usart1Init(115200);
ShowVersion();
__enable_irq();
}
#define BOOTLADER_SIZE ((uint32_t)1024 * 12)
#define BOOT_START_ADDRESS ((uint32_t)0x08000000)
#define BOOT_FLASH_END_ADDRESS ((uint32_t)BOOT_START_ADDRESS+BOOTLADER_SIZE-1)
#define BOOT_FLASH_SIZE (BOOT_FLASH_END_ADDRESS-BOOT_START_ADDRESS+1)
#define APP_START_ADDRESS ((uint32_t)(BOOT_FLASH_END_ADDRESS+1))
typedef void (*pFunction)(void);
__IO pFunction JumpToAplication;
void JumpToApp(void)
{
// printf("Run Application %x \n",(*(__IO uint32_t*)APP_START_ADDRESS));
if(((*(__IO uint32_t*)APP_START_ADDRESS) & 0x2ffe0000)==0x20000000)
{
printf("Go to application and runnig\n");
__disable_irq();
JumpToAplication=(pFunction)(*(__IO uint32_t*)(APP_START_ADDRESS+4));
__set_MSP(*(__IO uint32_t*)APP_START_ADDRESS);
JumpToAplication();
}
}
Application 程序设计:
#define APPLICATION_ADDRESS (uint32_t)0x8003000
#if (defined ( __CC_ARM ))
__IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));
#elif (defined (__ICCARM__))
#pragma location = 0x20000000
__no_init __IO uint32_t VectorTable[48];
#elif defined ( __GNUC__ )
__IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));
#elif defined ( __TASKING__ )
__IO uint32_t VectorTable[48] __at(0x20000000);
#endif
void IAPAPP_Init()
{
for(uint8_t i = 0; i < 48; i++)
{
VectorTable[i] = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));
}
/* Enable the SYSCFG peripheral clock*/
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Remap SRAM at 0x00000000 */
SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
}
int main(void)
{
//SCB->VTOR =((uint32_t)0x08003000);
IAPAPP_Init();
HardwareInit();
printf("Hello, welcome to application\n");
uint16_t TimeCount=0;
while(1)
{
if((TickCount>100)&&(TimeCount<1000))
{
TickCount=0;
printf("wait %d second\n",TimeCount);
TimeCount++;
}
}
return 1;
}
Application的keil设置:
详细工程见:https://download.youkuaiyun.com/download/liqiuhua2016/10962923
感谢网友:https://blog.youkuaiyun.com/jacycle/article/details/75697599
https://blog.youkuaiyun.com/losthome/article/details/70305978