首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

STM32-OTA升级

  • 25-03-07 21:42
  • 4407
  • 12726
blog.csdn.net

一、OTA(Over-The-Air)

        OTA(Over-The-Air)是一种通过无线通信方式,为设备分发新软件、配置甚至更新加密密钥的技术。它允许中心位置向所有用户发送更新,确保每个接收者都无法拒绝、破坏或改变这些更新,并且能够即时将更新应用到所有设备上。OTA升级适用于通过网络或蓝牙等无线通信方式进行,使得设备管理更加便捷和灵活,同时提升了系统的安全性和可维护性

在OTA固件升级中,单区模式和双区模式是两种常见的策略,各自有着特定的优缺点。

1)单区模式

        单区模式,整个升级过程仅使用一个存储区(通常是Bank0)。升级流程包括先擦除当前运行的老固件,然后直接将新固件下载到同一存储区,并对其进行有效性校验。这种模式优点在于节省Flash空间,实现简单直接,适用于资源有限的设备。然而,其缺点是风险较高,一旦升级失败或新固件不可用,设备可能会无法正常运行,需要外部干预才能恢复。

2)双区模式

        双区模式,老固件和新固件分别存储在不同的存储区(通常是Bank0和Bank1)。升级过程先将新固件下载到预留的下载区(Bank1),然后进行校验。校验通过后,系统进入Bootloader模式,将新固件从下载区复制到主运行区(Bank0),替换老固件。这种模式的优势在于安全可靠,即使升级失败,系统仍能回滚到之前的稳定版本,避免系统故障。它也提供了更高的灵活性,允许设备在升级过程中同时运行两个固件版本,确保平稳过渡。不过,双区模式需要额外的Flash空间来支持两个固件版本的存储,因此对资源的需求较高。

二、IAP(In Application Programming)

        IAP(In Application Programming,即在应用中编程),旨在实现用户应用程序的动态更新,而无需使用专门的编程工具或硬件。一般情况下,STM32芯片的代码区域只存放一个用户程序。通过使用IAP方案,可以将代码区域划分为两部分:一个是固定的引导加载程序(bootloader),另一个是用户应用程序(user application)。如图所示

在单片机上电时,系统首先进入引导加载程序(bootloader)。引导加载程序会检测预设的条件,例如检测按键是否按下、是否接收到特定的串口数据、或者U盘是否插入等。如果条件未被触发,引导加载程序将直接跳转到用户应用程序(user application)执行用户的应用逻辑。如果条件被触发,引导加载程序将执行以下步骤:

  1. 擦除用户应用程序:引导加载程序会擦除当前存储的用户应用程序代码区域,确保该区域是空的,以便接受新的用户代码。

  2. 重新写入用户代码:引导加载程序从外部源(如串口通信、USB设备等)接收新的用户应用程序数据,并将其写入到之前擦除的用户代码区域中。

三、FLASH地址分配

 1)普通程序的内部FLASH分配

        此时普通的应用程序占据内部Flash的大部分空间,包括主要的应用逻辑和功能代码。整个应用程序共享一个中断向量表,用于存储每个中断的入口地址,供所有的中断服务例程使用。

2)IAP方案的内部FLASH分配

        IAP方案在内置Flash的特定地址范围内增加了一个Bootloader程序。Bootloader的主要功能是通过串口或其他通信接口来更新或烧录用户应用程序。Bootloader程序有自己独立的中断向量表,专门处理引导过程中的中断和异常情况。用户应用程序仍然占据内部Flash的一部分空间,但更新和烧录可以通过Bootloader完成,而非传统的编程器。用户应用程序也有自己的中断向量表,确保在运行时正确处理中断事件。

3)示例

设置两个工程:Bootloader程序、UserApplication程序。以下是详细的设置说明:

        1)BootLoader程序

        Bootloader程序被安排在内部FLASH的第一页,起始地址为 0x0800 0000,占用20KB空间,地址范围从0x0800 0000到0x0800 4C00(页号0至19)。在执行跳转到UserApplication之前,需确保Bootloader关闭所有打开的中断或外设,以避免影响UserApplication的运行。

        2)UserApplication程序

        UserApplication程序从内部FLASH的第二页开始,起始地址为0x0800 5000,占用43KB空间,地址范围从0x0800 5000到0x0800 F800(页号20至62)。

        3)UserData

        内部FLASH的最后一页被保留用于UserData,占用1KB空间,起始地址为0x0800 FC00,页号为63。

如图所示:

第一页

最后一页

分区

容量

地址

页号

地址

页号

BootLoader

20KB

0800 0000

0

0800 4C00

19

UserApplication

43KB

0800 5000

20

0800 F800

62

UserData

1KB

0800 FC00

63

        4)生成UserApplication的bin文件

D:\Keill_v5\ARM\ARMCLANG\bin\fromelf.exe --bin Objects\Project.axf -o Project.bin
  • "D:\Keill_v5\ARM\ARMCLANG\bin\fromelf.exe" 是 fromelf.exe 工具的完整路径,根据实际情况需要修改成本地的路径。
  • Objects\Project.axf 是工程生成的 .axf 文件的路径和文件名,确保路径是正确的,可以根据实际情况进行调整。
  • -o Project.bin 指定生成的输出文件名为 Project.bin,可以根据需要修改输出文件名和路径

四、STM32启动流程概述

1)普通程序启动流程:
1. 内核初始化

 1)内核复位和NVIC寄存器部分清零

  • 在复位时,内核和NVIC相关寄存器被清零,确保系统处于可控状态。

2)设置堆栈

  • 内核从向量表的起始地址读取堆栈指针(SP_main),设置主堆栈指针(SP)。

3)设置PC和LR寄存器

  • PC寄存器被设置为复位中断向量的地址,LR寄存器通常设置为0xFFFFFFFF(复位值)。
2. 执行复位中断处理函数(Reset_Handler)

1)强制PC指针指向中断向量表的复位中断向量

  • 单片机的硬件会将PC指针自动定位到复位中断向量表的复位中断向量处,开始执行Reset_Handler函数。

2)Reset_Handler中的初始化步骤

  • 在Reset_Handler函数中,会调用SystemInit函数进行系统的初始化,包括时钟设置和中断向量表配置等。
3. 初始化全局/静态变量和重定位

1)调用 __main 函数

  • __main 函数由编译器生成,负责初始化全局/静态变量、执行重定位工作,并最终跳转到用户定义的main函数。
4. 跳转到main函数执行用户代码
  • 在所有初始化工作完成后,控制权被传递给用户编写的main函数,开始执行用户程序的主体逻辑。
2)引导加载程序启动流程:
1)内核初始化
  • 复位时,内核和NVIC寄存器被清零。
  • 设置堆栈和初始化PC、LR寄存器。
2)执行引导加载程序的复位中断处理函数(Bootloader Reset_Handler)
  • 硬件将PC指针定位到引导加载程序的复位中断向量处,开始执行引导加载程序的Reset_Handler函数。
  • 引导加载程序的初始化步骤,可能包括初始化引导加载程序自身的硬件资源和配置。
3)初始化全局/静态变量和重定位
  • 引导加载程序调用 __main 函数进行全局变量的初始化和重定位工作。
4)等待指令或判断是否需要进行IAP
  • 引导加载程序可能等待外部触发条件,如特定按键组合、串口指令等,来决定是否启动IAP流程。
5)启动固件更新(IAP过程)
  • 如果需要进行固件更新,引导加载程序会初始化相关硬件接口(如串口、USB等)以及存储器(如Flash)接口。
  • 下载新固件数据,对数据进行校验(CRC校验等)确保完整性。
6)擦除原有固件区域
  • 引导加载程序可能需要先擦除原有固件存储区域,以便存储新的固件数据。
7)写入新固件
  • 将通过IAP方式下载的新固件数据写入到目标Flash存储器中的指定位置。
8)校验和完成
  • 写入完成后,引导加载程序进行最终的校验,确保固件写入的正确性和完整性。
9)系统重启
  • 如果固件更新成功,引导加载程序可能会进行系统的最后配置和清理工作。
  • 然后重启系统,跳转到新固件的起始地址执行。
10)跳转到新固件执行
  • 控制权转移给新固件的Reset_Handler函数,开始执行新固件的初始化和主逻辑。

五、注意事项

        在下载bin文件的过程中,确保数据帧的完整性至关重要。一般情况下,串口使用空闲中断来判断数据帧是否传输结束。但在大量数据传输时,可能会出现空闲中断误判的情况。为了解决这个问题,可以考虑使用类似RS485通信的方式,通过定时器定时触发来确定数据传输的结束标志,例如设定一个100ms的空闲周期作为传输结束的标志。

注:本文转载自blog.csdn.net的J_Capital的文章"https://blog.csdn.net/Actkeying/article/details/140932436"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

124
嵌入式
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top