STM32的在线升级(IAP)实现方法:BOOT+APP原理详解

news2025/1/8 5:44:57

0 工具准备

Keil uVision5
Cortex M3权威指南(中文)
STM32参考手册

1 在线升级(IAP)设计思路

为了实现STM32的在线升级(IAP)功能,通常会将STM32的FLASH划分为BOOT和APP两个部分,BOOT就是引导APP的引导程序,当我们需要在线升级时就可以通过BOOT来实现。BOOT和APP在FLASH中的分布如下:
在这里插入图片描述

原理分析:
(1)当STM32复位后会跳转到FLASH首地址,也就是0x08000000的位置,读取1-4Byte获取主堆栈指针初始值(栈顶值)并设置,然后读取5-8Byte获取复位中断服务函数入口地址并执行,进入BOOT程序
(2)BOOT程序根据用户选择升级APP或者跳转到APP
(2.1)如果用户选择升级APP则擦除APP所在扇区,按照一定协议将APP程序复制到FLASH的APP扇区
(2.2)如果用户选择跳转到APP,首先失能全局中断,然后复位所有外设及RCC时钟,清除所有中断使能位及中断挂起标志,然后执行一些用户自定义的操作。最后设置主堆栈指针,跳转到APP的复位中断服务函数(相当于做了(1)中内核干的事情)。

2 BOOT设计

这里介绍一下BOOT跳转到APP函数的设计思路:

// 复位所有外设
void Per_DeInit(void)
{
    /* 复位APB1上的外设 */
    RCC->APB1RSTR = 0xFFFFFFFFU;
    RCC->APB1RSTR = 0x00U;

    /* 复位APB2上的外设 */
    RCC->APB2RSTR = 0xFFFFFFFFU;
    RCC->APB2RSTR = 0x00U;

    /* 复位AHB1上的外设 */
    RCC->AHB1RSTR = 0xFFFFFFFFU;
    RCC->AHB1RSTR = 0x00U;

    /* 复位AHB2上的外设 */
    RCC->AHB2RSTR = 0xFFFFFFFFU;
    RCC->AHB2RSTR = 0x00U;

    /* 复位AHB3上的外设 */
    RCC->AHB3RSTR = 0xFFFFFFFFU;
    RCC->AHB3RSTR = 0x00U;
}


// 跳转到APP
void Jump_to_APP(void)
{
    uint32_t i = 0;
    void (*SysMemBootJump)(void); /* 声明一个函数指针 */

    /* 关闭全局中断 */
    __disable_irq();

    /* 复位所有外设 */
    Per_DeInit();

    /* 设置所有时钟到默认状态,使用HSI时钟 */
    RCC_DeInit();


    /* 关闭所有中断,清除所有中断挂起标志 */
    for (i = 0; i < 8; i++)
    {
        NVIC->ICER[i] = 0xFFFFFFFF;
        NVIC->ICPR[i] = 0xFFFFFFFF;
    }

    /* 关闭滴答定时器,复位到默认值 */
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;

    /* 重设独立看门狗超时时间为5S */
    IWDG_Config(4, 3125);
    /* 喂狗,给APP预留一些时间 */
    Raise_Dog();

    /* 使能全局中断 */
    __enable_irq();

    /* APP首地址+4就是APP复位中断服务程序地址 */
    SysMemBootJump = (void (*)(void))(*((uint32_t *)(FLASH_APP_ADDR + 4)));

    /* 设置主堆栈指针 */
    __set_MSP(*(uint32_t *)FLASH_APP_ADDR);

	/* 设置为特权级模式,使用MSP指针 (BOOT是RTOS的一定要设置,否则后面的APP无法运行,最好都加上无伤大雅)*/
    __set_CONTROL(0);
    
    /* 跳转到系统BootLoader */
    SysMemBootJump();

    /* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */
    while (1)
    {
    }
}

相关知识:
(1)涉及到的复位寄存器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
复位寄存器写入1复位相应外设,写入不复位。
(2)涉及到的SysTick寄存器
在这里插入图片描述
SysTick->CTRL:SysTick控制及状态寄存器
SysTick->LOAD:SysTick重装载数值寄存器
SysTick->VAL:SysTick当前数值寄存器
(3)涉及到的NVIC寄存器
(3.1)NVIC->ICER,中断失能寄存器,写入1失能中断
在这里插入图片描述
(3.2)NVIC->ICPR,中断挂起清除寄存器,写入1清除中断挂起
在这里插入图片描述
(4)涉及到的内核控制寄存器
在这里插入图片描述
这里我们设置为0,也就是特权级的线程模式+选择主堆栈指针MSP,恢复到MCU复位状态(BOOT是RTOS的一定要设置,否则后面的APP无法运行,最好都加上无伤大雅)。
(5)APP二进制文件含义
bin文件:
在这里插入图片描述
Byte1-4:0x20014168
Byte5-8:0x080101A1
Byte9-12:0x08012D75
Byte13-16:0x08012851
map文件:
__initial_sp 0x20014168 Data 0 startup_stm32f40xx.o(STACK)
Reset_Handler 0x080101a1 Thumb Code 8 startup_stm32f40xx.o(.text)
NMI_Handler 0x08012d75 Thumb Code 2 stm32f4xx_it.o(i.NMI_Handler)
HardFault_Handler 0x08012851 Thumb Code 8 stm32f4xx_it.o(i.HardFault_Handler)
可以看到,APP工程的bin文件含义如下:
Byte1-4:0x20014168 主堆栈指针初始值(栈顶值)
Byte5-8:0x080101A1 复位中断服务函数地址
Byte9-12:0x08012D75 NMI中断服务函数地址
Byte13-16:0x08012851 HardFault中断服务函数地址
该部分的定义在STM32的参考手册上也可以看到:
在这里插入图片描述
其实,我们只需要关注主堆栈指针初始值(栈顶值)和复位中断服务函数地址即可。如果想要了解APP前几个byte的全部内容,可以参看STM32参考手册的“STM32F405xx/07xx 和 STM32F415xx/17xx 的向量表”。
弄清楚了上述的寄存器使用方法和APP的bin文件内容后,接下来BOOT中跳转到APP的操作原理就一目了然了:
(1)关闭全局中断,避免被打断
(2)复位所有外设,为APP营造一个纯净的环境
(3)设置所有时钟到默认状态,为APP营造一个纯净的环境
(4)关闭所有中断同时清除所有中断挂起标志,避免APP使能中断后异常触发等情况
(5)关闭滴答定时器,复位到默认值,为APP营造一个纯净的环境【自定义】
(6)重设独立看门狗超时时间为10s,喂狗给APP预留一些时间(独立看门狗一旦打开就无法关闭)【自定义】
(7)使能全局中断,避免APP部分没有打开全局中断(这时也清除了所有中断使能位,可以避免跳转到APP过程被中断打断)
(8)函数指针指向APP的复位中断服务函数(也就是APP的第5-8Byte)
(9)设置主堆栈指针(也就是APP的前4Byte)
(10)跳转到APP
以上有2个地方需要特别注意:
(1)APP的复位中断服务函数地址是APP的第5-8Byte
(2)APP的主堆栈指针初始值(栈顶值)是APP的前4Byte

3 APP设计

APP设计时只需要修改工程的flash起始地址以及中断向量偏移地址寄存器即可。
(1)修改FLASH起始地址
在这里插入图片描述
如果我们的APP存放在FLASH的0x8010000开始的位置,则将FLASHA的起始地址修改为0x8010000即可。
(2)修改中断向量偏移地址
BOOT下我们的中断向量偏移地址为0x08000000和默认值一样无须特别设置,APP下由于FLASH起始地址被修改到0x8010000,因此需要将中断向量偏移地址设置为0x1000:

#define VECT_TAB_OFFSET  0x10000

相关寄存器如下:
在这里插入图片描述
当STM32发生了中断需要响应时,内核会根据向量表偏移量寄存器的值在相应的FLASH空间找到异常服务函数入口地址(中断服务函数入口地址保存工作由编译器完成)。上电后的向量表如下:
在这里插入图片描述
假设我们设置的VTOR的值为0x8010000,在发生了硬错误时,会跳转到0x8010000+0x0000000C的位置找到硬错误中断服务函数地址并执行。这也是我们为什么需要在APP中设置VTOR的原因(BOOT里已经默认设置为0x0x8000000),保证我们的中断能够正确执行。

4 总结

(1)APP程序需要修改FLASH起始地址和向量表偏移量寄存器,以便内核能够在中断发生时进入正确的中断服务函数
(2)BOOT程序跳转到APP的过程实际上就是模拟内核的操作
(3)BOOT跳转到APP之前一定要失能所有中断、清除所有中断挂起标志,营造一个纯净的环境。最好将所有外设和RCC全部复位到初始值,使APP的环境更加贴近硬件复位后的环境。
(4)如果在BOOT内使能了独立看门狗,最好调整超时时间并喂狗保证在APP喂狗操作执行前预留足够的时间
(5)如果BOOT是RTOS,则一定要设置堆栈指针为MSP及特权级的线程模式
注意:
在这里插入图片描述
最好在BOOT内使能独立看门狗,当APP错误的时候依然能够触发复位(假如APP错误,会发生不可预知的错误,进入while(1)或其它地方看门狗均会减到0产生复位信号)。另外:独立看门狗的重载值是12位的,最大为4095!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1362275.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue组件封装

组件封装 一个封装好的组件可以在项目的任意地方使用&#xff0c;甚至我们可以直接从npm仓库下载别人封装好的组件来进行使用&#xff0c;比如iview、element-ui这一类的组件库。但是每个公司的需求是不一样的&#xff0c;我们可以封装自己的组件库并发布到npm上去&#xff0c…

【ONE·MySQL || 基本查询(CRUD)】

总言 主要内容&#xff1a;表的增删查改&#xff08;DML操作&#xff09;。insert插入&#xff08;包含插入更新、插入查询&#xff09;&#xff0c;replace替换。select查询&#xff08;包含列别名、distinct去重、where条件筛选、order排序、limit子句、group by子句、having…

【2023年度总结】多变的2023 | 成长的2023 | 蜕变的2023

文章目录 2023年&#x1f4cc;&#xff0c;对我来说2023年&#xff0c;是多变的一年&#x1f393;2023年&#xff0c;是挑战的一年&#x1f38a;2023年&#xff0c;是惊喜的一年&#x1f389;2023年&#xff0c;是好多第一次的一年&#x1f3a8; 2024年&#xff0c;是新的开始2…

计算机组成原理-进位计数制(进制表示 进制转换 真值和机器树)

文章目录 现代计算机的结构总览最古老的计数方法十进制计数法推广&#xff1a;r进制计数法任意进制->十进制二进制<--->八进制&#xff0c;十六进制 各种进制常见的书写方式十进制->任意进制整数部分小数部分 十进制->二进制&#xff08;拼凑法&#xff09;真值…

一起学docker(六)| docker网络

Docker网络 不启动docker&#xff0c;网络情况&#xff1a; 启动docker&#xff0c;网络情况&#xff1a; 作用 容器间的互联和通信以及端口映射容器IP变动时候可以通过服务名直接网络通信而不受影响 常用命令 docker network --help 查看docker网络相关命令docker network…

Elasticsearch:结合 ELSER 和 BM25 文本查询的相关搜索

Elastic Learned Spare EncodeR (ELSER) 允许你执行语义搜索以获得更相关的搜索结果。 然而&#xff0c;有时&#xff0c;将语义搜索结果与常规关键字搜索结果相结合以获得最佳结果会更有用。 问题是&#xff0c;如何结合文本和语义搜索结果&#xff1f; 首先&#xff0c;让我…

大数据 MapReduce如何让数据完成一次旅行?

专栏上一期我们聊到MapReduce编程模型将大数据计算过程切分为Map和Reduce两个阶段&#xff0c;先复习一下&#xff0c;在Map阶段为每个数据块分配一个Map计算任务&#xff0c;然后将所有map输出的Key进行合并&#xff0c;相同的Key及其对应的Value发送给同一个Reduce任务去处理…

1_开闭原则(Open Closed Principle)

开闭原则(Open Closed Principle) 1.概念 开闭原则&#xff08;Open-Closed Principle&#xff09;是指一个软件实体如类、模块和函数应该对扩展开放&#xff0c; 对修改关闭。所谓的开闭&#xff0c;也正是对扩展和修改两个行为的一个原则。强调的是用抽象构建框架&#xff…

“TypeError: Cannot read properties of null (reading ‘getContext‘)“

目录 一、报错截图 二、使用场景 三、代码截图 四、报错原因 五、解决办法 一、报错截图 二、使用场景 第一次在vue项目种使用canvas&#xff0c;跟着网上教程做&#xff0c;标签canvas写好了&#xff0c;dom元素获取了&#xff0c;简单“画”了一下&#xff0c;运行之后报…

基于Rangenet Lib的自动驾驶LiDAR点云语义分割与可视化

这段代码是一个C程序&#xff0c;用于处理来自KITTI数据集的激光雷达&#xff08;LiDAR&#xff09;扫描数据。程序主要实现以下功能&#xff1a; 1. **读取和解析命令行参数**&#xff1a;使用Boost库中的program_options模块来定义和解析命令行参数。这包括扫描文件路径、模型…

程序员副业之无人直播助眠

介绍和概览 大家好&#xff0c;我是小黑&#xff0c;本文给大家介绍一个比较轻松简单的副业&#xff0c;无人直播助眠副业。 这个项目的核心就是通过直播一些助眠素材来赚钱。比如你可以放一些舒缓的雨声之类的&#xff0c;吸引观众进来。然后&#xff0c;咱们可以挂个小程序…

K8Spod组件

一个pod能包含几个容器 一个pause容器(基础容器/父容器/根容器&#xff09; 一个或者多个应用容器(业务容器) 通常一个Pod最好只包含一个应用容器&#xff0c;一个应用容器最好也只运行一个业务进程。 同一个Pod里的容器都是运行在同一个node节点上的&#xff0c;并且共享 net、…

深度学习中的知识蒸馏

一.概念 知识蒸馏&#xff08;Knowledge Distillation&#xff09;是一种深度学习中的模型压缩技术&#xff0c;旨在通过从一个教师模型&#xff08;teacher model&#xff09;向一个学生模型&#xff08;student model&#xff09;传递知识来减小模型的规模&#xff0c;同时保…

了解Web 基础与 HTTP 协议

本章内容 了解静态网页与动态网页 理解 HTTP 协议的 GET 和 POST 方法 理解 HTTP 协议请求流程 随着互联网的高速发展&#xff0c;企业信息化应用大部分已采用网页的形式构建&#xff0c;掌握网页 的相关知识和 HTTP 的请求流程&#xff0c;是掌握互联网技术的第一步&#x…

分析C++软件问题的常用分析工具及案例集锦详解

目录 1、库依赖关系查看工具Dependency Walker 2、GDI对象查看工具GDIview 3、PE信息查看工具PeViewer/MiTeC EXE Explorer 4、进程信息查看工具Process Explorer 5、进程监控工具Process Monitor 6、API函数调用监测工具API Monitor C软件异常排查从入门到精通系列教程&…

聚道云软件连接器助力某半导体行业公司实现访客管理自动化

客户介绍&#xff1a; 某半导体行业公司是一家全球领先的半导体公司&#xff0c;在全球拥有众多研发中心和生产基地。该公司每天都有大量的访客来访&#xff0c;需要严格的访客管理制度。 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 客户痛点&#…

报错处理:java.io.IOException: Could not find resource mybatis-config.xml

运行mybatis文件时出现了以下的情况 java.io.IOException: Could not find resource mybatis-config.xmlat org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:114)at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:100)at org.apach…

【数据库系统概念】第7-14章集合

文章目录 第七章 数据库设计和E-R模型&#xff08;重点&#xff01;&#xff01;&#xff01;&#xff09;~~7.1 设计过程概览&#xff08;了解&#xff09;~~7.1.1 设计阶段7.1.2 设计选择 7.2 实体-联系模型&#xff08;重点掌握&#xff09;7.2.1 实体集7.2.2 联系集联系集的…

Spring配置提示: File is included in 4 contexts

问题描述&#xff1a; spring配置文件上面提示&#xff1a; mvc application context in module studyDemo file is included in 4 contexts 导致原因&#xff1a;因为所有的配置文件都没有放在同一个上下文中 所谓File is included in 4 contexts是因为spring的配置文件放…