我们需要实现的任务是不需要去切换BOOT pin的状态来升级我们的程序。
1.硬件必须从flash 启动。如下图BOOT0必须接低电位。
2. flash 地址分配,根据所用芯片flash 大小,可以从选型手册查看。 例如STM32F103C8为64K
我们可以根据bootloader和APP大小分配。这里我如下分配
bootloader 30K IROM1 如下配置,0x7800,是30K转换成16进制填入。 此flash需要1k的倍数。有的需要2k倍数,看手册。
APP 32k IROM1 如下配置:
剩下空闲区,放一些bootflag等一些参数,可以供bootloader和app使用而不会被擦除。
3.bootloader 代码部分。
void (*jump2app)();
void iap_load_app(u32 appxaddr)
{
if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //appxaddr为app烧录地址,这里是0x8007800¨,我们可以通过memory查看内容,第一个地址存0x2开头的栈顶地址。如果烧录,这个地址可以判断通过。
{
jump2app=(void(*)())*(vu32*)(appxaddr+4); // appxaddr+4 就是程序复位地址
MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针
__disable_irq(); //关闭中断
jump2app(); //跳转
}
}
bootloader 部分加入这部分代码,就可实现跳转。这里我们在flash 中增加bootflag标志位。
if(bootflag) //如为真,直接跳到app,为假进入bootloader,可升级程序。
{
iap_load_app(userapplication);
}
4. app代码部分
在system_stm32f10x.c
#define VECT_TAB_OFFSET 0x8007800
void SystemInit (void)中最下面增加
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
以上中断向量表一定要做,不然中断例如串口中断还会跳到bootloader中。如果需要回到bootload,只要在app中bootflag写为假。因为程序,都是从bootloader程序开始运行决定跳转不跳转的。
5.调试
可以打开两个工程项目,bootloader和app都可以单独调试,但是调试app时,必须已经烧录了bootloader程序,调试时,直接会跳转到app代码调试,如果没有bootloader,app无法调试。
6.串口烧录部分
以上调试完后,bootloader中可接收写flash,这部分需研究flash擦除,读写操作,并将app转成bin如下图设定,既能产生bin,再将bin文件传送给bootloader后,写入要求地址。也可在bin文件中加入参数信息,便于bootloader处理。
5.问题点
*下面函数一般都是直接用的,里面做了向量表的定义,划线部分,一定要注释掉,不然前面做的中断向量表的重映射就没用。 一定要注意,容易忽视。
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Enable the USART1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //???????1??
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //???????0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //????
NVIC_Init(&NVIC_InitStructure); //???
}
6.结语
流程走完后,感觉不难,过程中反反复复,后面完善bootloader代码。