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

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!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript:关系数组、对象的复制

关系数组(关联数组)解字符串出现的次数: var str aaccddvvasdadqwd;// 统计每个字母出现的次数// 关系数组(关联数组) 长度永远为0// 使用字符串当做索引var arr [];arr[0] 20;// arr[a] 1;// arr[b] 3;// arr[c] 4;// console.log(arr)for (var i 0; i < str.lengt…

美经济学家预测,明年美股或将大跌86%,你怎么看?

年初至今&#xff0c;标准普尔500指数上涨25%&#xff0c;道琼斯指数上涨13%&#xff0c;以科技股为主的纳斯达克指数大涨了44%。 美国经济学家哈里斯登特近日预测&#xff0c;这种牛市是“100%人为印钞的结果”&#xff0c;而这一巨大的泡沫将在2024年破灭&#xff0c;届时美…

“智慧”千里眼助力水泵站

泵站是为水提供势能和压能&#xff0c;解决无自流条件下的排灌、供水和水资源调配问题的唯一动力来源&#xff0c;在工农业用水、防洪、排涝和抗旱减灾等方面发挥着重要作用。一旦出现异常&#xff0c;对经济生产将造成难以估量的损失&#xff0c;给水利安全管理造成负担。因此…

反射UnityEditor.GameView设置GamePlayMode分辨率

现在很有游戏考虑横屏适配、竖屏适配、阿拉伯语适配&#xff08;横竖屏&#xff09;导致拼界面变得越来越繁琐。 有很多时候需要记录各个控件的状态。 为了减少操作&#xff0c;特意制作了这个工具&#xff0c;点击用x配置可以自动切换到 宽高分辨率&#xff0c;如果当前没有则…

简易视频播放器(案例)

介绍 本篇Codelab使用ArkTS语言实现视频播放器&#xff0c;主要包括主界面和视频播放界面&#xff0c;我们将一起完成以下功能&#xff1a; 主界面顶部使用Swiper组件实现视频海报轮播。主界面下方使用List组件实现视频列表。播放界面使用Video组件实现视频播放。在不使用视频组…

程序员必知!命令模式的实战应用与案例分析

命令模式是一种行为设计模式&#xff0c;它将请求封装为对象以实现客户端参数化、请求排队、日志记录及撤销操作&#xff0c;旨在解耦调用者与操作实现者&#xff0c;以智能家居为例&#xff0c;用户通过界面发送命令对象&#xff0c;设备作为接收者执行相应操作&#xff0c;无…

物理与网络安全

物流环境安全 场地选择考虑抗震、承重、防火、防水、供电、空气调节、电磁防护、雷击及静电 场地因素&#xff1a; 自然灾害&#xff0c;社会因素&#xff08;加油站、化工厂&#xff09;&#xff0c;配套条件&#xff08;消防&#xff0c;交通&#xff0c;电力&#xff0c;…

QT项目中添加资源文件和使用qss样式

时间记录&#xff1a;2024/1/6 一、添加使用资源文件 1.1 创建项目并打开项目&#xff08;带ui界面的项目&#xff09; 1.2 使用快捷键Ctrln创建文件&#xff0c;选择"QT"下面的"QT Resource File" 1.3 输入文件名和文件保存路径 1.4 将需要添加的文件…

钡铼网关 只需一台,解锁智慧无人搅拌站系统,绿色又环保

行业需求 为了提高搅拌站的自动化&#xff0c;减少人工繁琐的操作&#xff0c;同时记录物料的增减记录&#xff0c;实现对于物料从进场到出场的全周期管理。 系统介绍 针对搅拌站各个环节的需求大致相同&#xff0c;市场中逐渐流行一整套基本的智慧搅拌站解决方案。各种搅拌站…

水母目标检测数据集VOC格式500张

水母&#xff0c;一种美丽而神秘的海洋生物&#xff0c;以其独特的形态和生态习性而备受瞩目。 水母的体型呈伞状&#xff0c;身体透明&#xff0c;有各种颜色和花纹。它们没有骨骼&#xff0c;身体由胶状物质组成&#xff0c;非常柔软和脆弱。水母通过触手上的刺细胞释放毒素…

哪个洗地机质量好?2024年洗地机推荐

如今&#xff0c;家用洗地机已经成为越来越多家庭的不可或缺之物。然而&#xff0c;在市场上琳琅满目的洗地机品牌和型号中&#xff0c;究竟哪一个性价比高、质量好&#xff0c;很多消费者常常陷入选择困难。为了帮助大家能够更加轻松地购买到适合自己的洗地机&#xff0c;我们…

dotdotdot插件快速实现多行文本的省略

jQuery.dotdotdot 前言 在“css新增文本样式&#xff08;完整&#xff09;”这篇&#xff0c;我们介绍了text-overflow属性省略多余的文本。用text-overflow属性可以直接省略单行文本&#xff0c;但省略多行文本&#xff0c;单独使用CSS是无法实现&#xff0c;今天我们介绍一…

【Linux 内核源码分析】关于Linux内核源码目录结构

Linux内核源码采用树形结构。功能相关的文件放到不同的子目录下面&#xff0c;使程序更具有可读行。 使用Source Insight打开源码&#xff0c;如下图所示&#xff0c;可以看到源码是树形结构。 目录含义描述arch存放与体系结构相关的代码&#xff0c;包括不同硬件平台的特定代…

深度解析分布式算法:构建高效稳定的分布式系统

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

高校选课系统需求分析开发源码

高校学生选课报名系统包括学生、教师和管理员三方的功能需求&#xff0c;学生的需求是查询院系的课程、选课情况及个人信息修改&#xff1b;教师则需要查看和查询所有课程信息及自己的课程信息以及教师信息的修改&#xff1b;管理员则负责更为复杂的任务&#xff0c;包括对学生…

2023年阿里云云栖大会:前沿技术发布与未来展望

在2023年的阿里云云栖大会上&#xff0c;我见证了云计算和人工智能领域的又一历史性时刻。这次大会不仅是对未来科技趋势的一次深入探索&#xff0c;更是阿里云技术实力和创新能力的集中展示。 首先&#xff0c;千亿级参数规模的大模型通义千问2.0的发布&#xff0c;无疑将人工…

【大厂秘籍】系列 - Java多线程面试题

Java多线程面试题 友情提示&#xff0c;看完此文&#xff0c;在Java多线程这块&#xff0c;基本上可以吊打面试官了 线程和进程的区别 进程是资源分配的最小单位&#xff0c;线程是CPU调度的最小单位 线程是进程的子集&#xff0c;一个进程可以有很多线程&#xff0c;每条线…

【MongoDB】MongoDB查询语句find的使用,和提高查询速度的游标的使用,非常详细!!!

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;MongoDB数据库 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继续前…

MySQL基础篇(三)约束

一、概述 概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 目的&#xff1a;保证数据库中数据的正确、有效性和完整性。 分类&#xff1a; 注意&#xff1a;约束是作用于表中字段上的&#xff0c;可以在创建表/修改表的时候添加约束。 二…

Java BIO、NIO、AIO、Netty知识详解(值得珍藏)

1. 什么是IO Java中I/O是以流为基础进行数据的输入输出的&#xff0c;所有数据被串行化(所谓串行化就是数据要按顺序进行输入输出)写入输出流。简单来说就是java通过io流方式和外部设备进行交互。 在Java类库中&#xff0c;IO部分的内容是很庞大的&#xff0c;因为它涉及的领…