STM32 OTA升级原理分析

本文详细介绍了STM32的正常程序和含bootloader程序的运行流程,包括程序结构、启动流程及中断处理。同时,讨论了多种固件升级策略,如无备份区、有备份区、AB对称升级和有工厂代码区升级,分析了各自的优缺点。还特别提到了TC397SOTA的硬件OTA方案,及其在程序跳转和中断向量表偏移设置上的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

程序运行流程

正常程序运行流程

在这里插入图片描述

程序结构

  • 正常程序从起始地址(0x08000000)开始写入
  • 中断向量表(地址:0x08000004)用于存储中断处理程序向量。
  • 中断处理函数(0x08000004+n)用于各种中断服务函数。
  • main函数(0x08000004+N),一个死循环,存放用户处理程序

程序启动流程

  • 系统复位启动,从中断向量表中取出复位中断向量
  • 跳转到复位中断处理函数,执行复位中断函数完成启动,跳转到main函数入口。
  • 执行main函数循环。
  • 中断产生,STM32硬件强制将PC指针指向中断向量表
  • 根据中断源选择相应中断处理函数向量
  • 跳转到对应中断处理函数,处理中断。
  • 中断函数结束,PC指针跳回main函数执行

含bootloader程序运行流程

在这里插入图片描述

程序结构

  • 正常程序从起始地址(0x08000000)开始写入
  • 中断向量表(地址:0x08000004)用于存储中断处理程序向量。
  • 中断处理函数(0x08000004+n)用于各种中断服务函数。
  • IAP main函数(0x08000004+N),一个死循环,存放用户处理程序
  • APP 中断向量表(地址:0x08000004+N+M)用于存储中断处理程序向量。
  • APP main函数(0x08000004+N+M+n),一个死循环,存放用户处理程序

含bootloader程序启动流程

  • 系统复位启动,从中断向量表中取出复位中断向量
  • 跳转到复位中断处理函数,执行复位中断函数完成启动,跳转到main函数入口。
  • 执行bootloader main函数,此时bootloader main函数内部有APP下载程序和跳转程序,执行跳转程序后会跳转到新程序的中断向量表,得到app程序的复位中断向量。
  • 跳转到APP复位中断处理函数,执行复位中断函数完成启动,跳转到APP main函数入口。
  • 中断产生,STM32硬件强制将PC指针指向Bootloader中断向量表
  • 程序再根据我们设置的中断向量表偏移量,得到对应中断源新的中断服务程序向量
  • 跳转到对应中断处理函数,处理中断。
  • 中断函数结束,PC指针跳回main函数执行

程序编程重点

存储分区

常见分区方案

无备份区升级

bootloader区 + APP code区

  • 升级流程:bootloader接收升级app,校验无误后写入APP code区,随后跳转到app
  • 优缺点:优点是APP code区体积大,支持较大APP升级。缺点:没有备份代码,升级过程中出错,升级失败,原有代码也会被破坏。
有备份区升级

bootloader区 + APP code区 + Updata区

  • 升级流程:APP code中接受升级APP,存放至updata区,校验无误后写入标志位,复位重启进入bootloader,bootloader将updata区代码复制到app区域,随后跳转至App code区。
  • 优缺点:优点:始终保持至少有一份代码可以运行,即使升级过程中程序中断,设备不会崩溃。缺点:bootloader程序执行周期长,升级比较慢。程序无法回退版本。
AB对称升级

Bootloader区 + APP code_A区 + APP code_B区

  • 升级流程:AB区地位等同,A区执行时接收升级代码到B区,重启后跳转到B区执行代码,再次升级时接收升级代码到A区,复位重启后跳转到A区执行。
  • 优缺点:优点:代码可回退版本,升级过程中出现意外不影响原代码执行。缺点:分区多,APP空间小,限制了代码量。
有工厂代码区升级

bootloader区 + Factory code区 + APP_A区 + APP_B区

  • Factory区用于存储出厂程序,AB分区对称升级。此外APP内有回复出厂设置选项,可以恢复出厂程序。
  • 常见于智能物联网设备,ESP32中有此功能
TC397 SOTA

与其他OTA不同,TC397有硬件OTA方案,TC397内部flash有六块flash,两种地址映射方式。正常地址映射编址:PF0 1 2 3 4 5 ,除此之外还有一种编制方式PF2 3 0 1 5 4 。正常代码存储在0 1存储块中,程序中可把升级代码存储到2 3块中,然后切换编制方式,下次复位运行,程序直接会从2 3 代码块执行。升级方案更简单

Bootloader

升级判断处理

程序跳转函数

此处用到了函数指针的知识,关于函数指针可以搜索一下:函数指针与指针函数区别和用法。函数指针本质上是指向函数的指针,用于调用函数。

typedef void (*iapfun)(void);      //定义一个函数类型参数
iapfun jump2app; 		//

void iap_load_app(u32 appxaddr)
{ 
	if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)	//检查栈顶地址是否合法
	{ 
		jump2app=(iapfun)*(vu32*)(appxaddr+4);		//用户代码区第二个字为程序开始地址
		MSR_MSP(*(vu32*)appxaddr);					//初始化APP堆栈指针
		jump2app();									//跳转到APP
	}
}

APP

APP程序为最终执行的用户程序。

程序存储地址

在这里插入图片描述

  • IROM1 Start: 代码起始地址
  • IROM1 Size:代码存储区大小

注意:APP code大小应小于size,一般放在bootloader后面,且地址便宜为0x200倍数。

设置程序中断向量表偏移

在SystemInit 函数中有代码如下:

  /* Configure the Vector Table location add offset address ------------------*/
#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

其中VTOR寄存器存放中断向量表起始地址,默认VECT_TAB_SRAM没有定义,所以SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET生效。VECT_TAB_OFFSET即为中断向量表偏移量,我们只需修改VECT_TAB_OFFSET即可使中断向量地址偏移。例如:

SCB->VTOR = FLASH_BASE | 0x10000; //设置中断向量表偏移0x10000
### STM32 OTA 更新实现方法 STM32 的 Over-the-Air (OTA) 更新是一种通过无线网络远程升级设备固件的技术。这种技术广泛应用于物联网领域,能够显著降低维护成本并提高系统的灵活性。以下是关于 STM32 OTA 实现的关键技术和常见方案。 #### 1. **双分区机制** 为了支持安全可靠的 OTA 升级,通常采用双分区存储结构。在这种设计中,微控制器的 Flash 被划分为两个主要区域:Active Partition 和 Inactive Partition。当设备启动时,默认加载 Active Partition 中的程序;而在 OTA 过程中,新版本固件被下载到 Inactive Partition 并验证其完整性[^2]。一旦确认无误,则切换引导地址至新的分区完成更新。 ```c // 示例代码展示如何设置向量表偏移以改变启动位置 SCB->VTOR = FLASH_BASE | (new_partition_address & 0x1FFFFF); ``` #### 2. **Bootloader 设计** 一个功能完善的 Bootloader 是成功实施 STM32 OTA 的核心组件之一。它负责管理整个升级流程,包括但不限于接收数据包、校验文件哈希值以及最终执行跳转操作等环节。常见的通信协议有 UART, SPI, Ethernet 或者 Wi-Fi/Bluetooth 等方式传输二进制映像给目标节点[^3]。 - 数据分帧处理逻辑需考虑缓冲区大小限制; - 使用 CRC32 或 SHA-256 对接收到的内容做一致性检测; ```python import hashlib def calculate_sha256(data): sha256_hash = hashlib.sha256() sha256_hash.update(data) return sha256_hash.hexdigest() received_firmware_checksum = "examplechecksum" if received_firmware_checksum == calculate_sha256(firmware_binary): print("Checksum verified successfully.") else: raise Exception("Invalid firmware checksum!") ``` #### 3. **安全性考量** 由于涉及敏感信息交换,在线刷写过程中必须采取适当措施防止未授权访问或者篡改行为发生。可以引入加密算法保护传输链路,并且仅允许经过认证的服务端推送合法镜像文件给客户端设备[^4]。 - AES-GCM 提供既保密又防伪的功能组合; - TLS 握手过程建立信任关系前先互相出示数字证书; --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值