STM32 OTA-IAP设计方案
OTA是Over-the-Air的简写,即空中下载技术,通过网络远程给用户进行系统更新和升级。IAP是In Application Programming的简写,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。IAP主要包括BootLoader和应用程序两部分,基于IAP的OTA设计思路是先通过OTA接收升级固件,再利用IAP进行固件搬移、校验和程序跳转,实现空中升级的目的。
BootLoader程序根据判断是否需要升级固件,并进行运行代码跳转。APP工程中需要编写OTA数据包交互协议,将接收到的升级固件保存至FLASH,校验一致性然后设置升级标志位并重启。
一、STM32启动模式分析
Cortex-M3 内核启动有3种情况:
- 通过boot引脚设置可以将中断向量表定位于SRAM区,即起始地址为0x2000000,同时复位后 PC 指针位于0x2000000处。
- 通过boot引脚设置可以将中断向量表定位于FLASH区,即起始地址为0x8000000,同时复位后PC指针位于0x8000000处。
- 通过boot引脚设置可以将中断向量表定位于内置Bootloader区。
Cortex-M3内核规定,起始地址必须存放栈顶指针,而第二个地址则必须存放复位中断入口向量地址,在Cortex-M3内核复位后,会自动从起始地址的下一个32位空间取出复位中断入口向量,跳转执行复位中断服务程序。Boot引脚设置见下表。
BOOT0 | BOOT1 | 启动模式 |
---|---|---|
0 | 无关 | FLASH |
1 | 0 | 系统存储器,ISP模式 |
1 | 1 | SRAM,调试 |
STM32的启动文件(startup_stm32f103xb.s)和启动过程。
(1)首先对栈和堆的大小进行定义,并在代码区的起始处建立中断向量表,其第一个表项是栈顶地址(32位),第二个表项是复位中断服务入口地址;(2)然后执行复位中断,在复位中断服务程序中跳转 C/C++标准实时库的main函数(__main),完成用户堆栈等的初始化后,跳转.c 文件中的main函数(真正的用户main函数)开始执行程序。
假设STM32被设置为从内部FLASH启动,中断向量表起始地位为0x8000000,则栈顶地址存放于0x8000000处,复位中断服务入口地址存放于0x8000004处。当STM32遇到复位信号后,则从0x80000004处取出复位中断服务入口地址,继而执行复位中断服务程序,然后跳转__main函数,最后进入main函数。
二、FLASH分区
设置STM32为从FLASH启动,即硬件设置管脚BOOT0低电平。本方案单片机型号采用:STM32F103RBT6,FLASH:128KB, SRAM:20KB。FLASH分为Bootloader、APPA、APPB、Parameter4个部分,分别占用20kB、50kB、50kB和8kB内存空间。APPA是应用程序区,运行用户设计的应用程序;APPB是应用程序备份升级区,存放接收到的固件升级包;Parameter是参数区,保存程序运行的关键参数、升级标志和密钥。FLASH分区示意图如下图所示。
三、OTA流程
单片机上电后首选运行BootLoader该段代码,读取Parameter参数区的升级标志量,判断是否有升级需求。若有升级需求,则根据记录的相应固件大小将APPB区升级文件拷贝至APPA区,并改写升级标志量,然后重启;若无升级请求,则程序跳转至APPA代码区运行。OTA程序流程如下所示。
具体流程描述如下:
Step1:上电启动单片机,首先执行BootLoader程序。
Step2:BootLoader读取Parameter区参数,查看升级标志是否有升级任务,若没有升级任务,则进入 Step3,否则进入 Step4。
Step3: BootLoader程序跳转至APPA,执行用户代码,并判断是否收到升级任务请求,若有升级任务请求则进入 Step7。
Step4:根据Parameter区升级参数,校验APPB固件数据并将APPB升级固件拷贝到APPA区,执行 Step5 和 Step6。
Step5:将升级标志位清除。
Step6:重启,再次执行BootLoader。
Step7:将接受到的升级数据包存入APPB区,并将相关升级参数存入Parameter区,若接收数据完成,固件检验通过则写入Parameter区升级标志,并进入 Step8 。
Step8:重启,再次执行BootLoader。
四、工程设置
4.1 BootLoader工程设置
由于BootLoader需要在上电复位后首先执行,因此,设置BootLoader存放在FLASH起始位置0x08000000,在MDK中打开options for target,设置IROM1 Start = 0x08000000,Size = 0x5000(0x5000 = 20kB),在Flash Download中设置下载Flash位置,参数与IROM1中设置Start和Size相同。BootLoader代码大小不超过20kB,越小越好。
4.2 APP工程设置
根据FLASH分区,APP代码存放在紧挨着BootLoader之后,因此APP的起始位置应该为0x08000000+0x5000 = 0x08005000,占用内存大小为0xC800(50kB),在MDK中打开options for target,设置IROM1 Start = 0x08005000,Size = 0xC800,在Flash Download中设置下载Flash位置,参数与IROM1中设置的Start和Size相同,如图5和图6所示。由于APP代码运行的起始位置不在0x08000000,其栈顶地址发生偏移,对应的中断向量表地址也整体发生偏移,因此,在代码中需要对APP代码的中断向量表偏移进行设置,具体的在system_stm32f1xxx.c中启动代码中可以看到定义的中断向量表偏移量宏定义:
#ifdef VECT_TAB_SRAMSCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#elseSCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET 0x5000 /*!< Vector Table base offset field. This value must be a multiple of 0x200. */
升级界面如下:
设备启动界面如下:
下一篇准备写个具体实现,包括本文提到的整包升级和朋友提到的差分升级,并且附带配套的QT开发的升级软件开发教程,考虑收费栏目。
有需求的朋友请私信,我统计一下情况。