IAP升级的本质就是将固件文件(.bin文件)写入到flash区域的某个地方,便于程序PC指针能够访问到代码数据。
注意有以下几点:
1.需要类似于BootLoader的一段程序。作用是将下载到备份区域的固件数据,从备份区域复制到APP运行区域。
实现:
①需要实现flash读写驱动,用于复制读写在flash区域中的固件数据
②需要跳转程序BootLoader-->APP运行
③需要在跳转的过程中,将所用的外设全部deinit
④设置栈指针,并跳转:
(部分代码)
/* Test if user code is programmed star
ting from address "APPLICATION_ADDRESS" */
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
JumpToApplication = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
JumpToApplication();
}
2.APP程序作用是将远程固件通过某种
通信方式获取下来(一般是串口,或者是基于串口的网络通信方式;或者是网口等)。将获取下来的固件写入到指定的flash区域中,并设置升级标记,使BootLoader能够知道并且复制固件。 实现:
①需要通过串口获取固件数据。使用Ymodem协议,协议中有整一套的数据传输校验和可靠逻辑。我们仅仅需要实现串口驱动API和flash读写API即可 ②固件写入完成后,需要重启系统,使之能够运行BootLoader程序,对备份区的固件进行复制。
③也是APP中最重要的一点,需要再APP--main函数一开始的位置就设置中断向量表偏移值:
SCB->VTOR = FLASH_BASE | 0x00004000; /* Vector Table Relocation in Internal FLASH */。 0x00004000为人为指定的偏移值(可以根据自己的APP和BootLoader程序的大小进行合理的选择,但是要注意此值必须要是0x200的整数倍,
STM32源码中有说明,请注意。否则跳转不成功)。
3.Keil的设置:
①BootLoader项目工程需要将target里面的IROM1设置为0x8000000
②APP项目中需要将target里面的IROM1设置为0x8004000(也就是你设置的实际偏移值,但是基础都是以0x8000000为主,然后|上偏移值)
4.关于Ymodem协议要注意一点:
①协议中这行代码Serial_PutByte(CRC16);在Serial_PutByte(ACK);之后,建议将CRC16这行代码删除,有时候会造成协议错乱。
(这个我也调试了很久,坑死了哈哈哈!!!)。 整个传输的过程使用的是串口轮询方式发送和接收,所以要注意轮询的阻塞时间,根据实际情况调整。
5.建议几点:
①BootLoader中不要有重试和死循环,出现异常后直接跳转到APP正常运行,等待下一次升级请求
②APP中需要有标记位用于和BootLoader通信,让BootLoader知道是否需要升级和升级信息相关。
③BootLoader跳转的时候一定要注意将其他外设deinit。(如果用到某些应用类型的中断可以尝试关闭调试一下。我的代码在跳转程序过程中并没有关闭中断,仅仅将外设deinit)
原作者:Liutao