思路
参考了许多大佬的文章;确定自己的需求{通过modbus传输固件,bootloader尽可能的小}
重点:固件转储、设置中断向量表、跳转栈指针
固件转储:modbus是以寄存器为单位存储数据的,在条件允许的情况下应开辟较大的内存用于存储固件程序,例如64字节,也就是32的寄存器;接收后的数据要保存在新的APP地址上;
设置中断向量表:在APP程序的开始,调用
SCB->VTOR = APP_ADDRESS;
APP_ADDRESS为当前app程序的flash地址,例如0x0800f000;
跳转栈指针:这里参考的正点原子的IAP升级程序:
//跳转到应用程序段
//appxaddr:用户代码起始地址.
void iap_load_app(u32 appxaddr)
{
if((((vu32)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法.
{
jump2app=(iapfun)(vu32)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址)
MSR_MSP((vu32)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
jump2app(); //跳转到APP.
}
}
由于要求bootloader非常小,所以只保留了跳转功能,固件接收,解码都放在了app中;
只有1k不到的flash占用,刚好在一个页里;
接收完固件后会重启单片机而免去了失能中断的步骤;如若不然,则需要禁用全局中断,在清除每个中断的标志位,{HAL_NVIC_ClearPendingIRQ}不清除的话,在重新失能后,中断会立即响应