【[STM32]标准库-自定义BootLoader】
[STM32]标准库-自定义BootLoader
- Bootloader
- Bootloader的实现
- BOOTloader工程
- APP工程
Bootloader
bootloader其实就是一段启动程序,它在芯片启动的时候最先被执行,可以用来做一些硬件的初始化或者用作固件热更新,当初始化完成之后跳转到对应的应用程序中去。
bootloader程序需要通过下载器烧写到芯片中,而APP则可以通过有线方式的UART、IIC、USB、SPI等总线来通过bootloader来更新,视所设计的bootloader程序而定。另外,对于无线方式热更新APP,一般是用WiFi、bluetooth通过UART透传的方式烧写芯片APP程序。
Bootloader的实现
本次采用STM32F429IGT6单片机,Flash共有1MB大小,SRAM共有256KB。
本次设计一个Bootloader和一个APP程序,空间分别如下:
BOOTloader程序起始地址0x0800 0000分配大小为0xA000,40KB,
注意按照扇区对齐(比如4KB一个扇区)
APP程序起始地址0x0800 A000分配的大小为0xF6000,984KB。
STM32的中断向量表和栈顶地址
STM32Fx有一个中断向量表,这个中断向量表存放代码开始部分的后4个字节处(即0x08000004),代码开始的4个字节存放的是栈顶地址。
栈是从高到低分配,高地址到低地址
堆是从低到高分配,低地址到高地址
排列格式如下
我们知道一般情况下,我们下载的代码放在0x08000_000这个位置,为了实现bootloader,我们可以将下载代码的位置整体往后挪一段空间,比如我们挪到0x0800_3000,那么这之前挪动空出来的一段空间,我们就可以用来存放我们的bootloader程序。系统上电后先运行bootloader,bootloader决定是否要更新app,最后跳转到0x0800 3000这个位置执行。
上图为SystemInit中修改用户app存放位置(0x0800 3000)的地方,SystemInit在启动文件中用到,它会在复位后,在main函数运行之前运行;

BOOTloader工程
bootloader和App都是完整的STM32工程,区别在于工程所实现的功能和占用Flash的大小。由于Bootloader的功能比较单一,并且为了节约Flash留给用户App,Bootloader一般不带操作系统,所占用的Flash较小。APP是完整的用户程序,按照正常的设计流程进行设计,只需要在工程配置和部分初始化代码处进行修改。
设置工程起始地址,及其大小
中断向量表的地址偏移
调用函数NVIC_SetVectorTable()进行配置。BOOT工程一般不需要配置
执行BOOT后,跳转到APP程序中
注意点:
检查堆栈地址是否有效,单片机的RAM大小为0x30000,0x3000 0000 - 0x3000 = 0x2FFD 0000,也可以用其他方法来计算RAM是否超过单片机的范围
关闭全局中断,__set_PRIMASK(1);仅只剩下NMI 和硬 fault 可以响应,记得在APP工程设置__set_PRIMASK(0);
复位BOOT工程中用到的外设
函数指针赋值为Reset_Handler向量的地址
设置堆栈地址
跳转到APP中
typedef void (*Run_APP_t)(void);
/**
-
@brief 跳转并执行到APP程序
-
@param APPProgramAddr : APP程序的地址
-
@retval None
/
static void Jump_to_APP(uint32_t APPProgramAddr)
{
Run_APP_t run_app = (Run_APP_t)((uint32_t*)(APPProgramAddr + 4));/* 检查堆栈地址(RAM地址)是否有效,然后跳转到用户应用程序 /
if(((uint32_t*)APPProgramAddr & 0x2FFD0000) == 0x20000000)
{
/*
关闭所有中断,
在它被置 1 后,就关掉所有可屏蔽的异常,只剩下NMI 和硬 fault 可以响应。
它的缺省值是 0,表示没有关中断。
*/
__set_PRIMASK(1);/* 复位所有已经开启的外设 */ GPIO_DeInit(GPIOH); GPIO_DeInit(GPIOA); GPIO_DeInit(GPIOC); EXTI_DeInit(); CRC_ResetDR(); USART_DeInit(USART1);/* 设置堆栈指针 */
// __set_PSP((uint32_t)APPProgramAddr);
// __set_CONTROL(0);
__set_MSP((uint32_t)APPProgramAddr);
/* 跳转到APP程序中执行 */run_app();
}
else
{USART1Printf("BOOT_ERROR1!\r\n");
}
}
APP工程
Flash的起始地址,大小
中断向量表偏移地址和开启全局中断
/* 设置中断向量表 /
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0xA000);//中断向量表偏移
/
关闭所有中断,
在它被置 1 后,就关掉所有可屏蔽的异常,只剩下NMI 和硬 fault 可以响应。
它的缺省值是 0,表示没有关中断。
*/
__set_PRIMASK(0);
Keil5生成BIN文件
fromelf --bin -o “$L@L.bin” “#L”
注意点:上电应检查标志位,不能初始化任何外设,根据该标志位来决定是否进入APP
通过软件复位给 APP 一个干净的系统
这里的标志位存在RTC备份寄存器0中,占用4个字节
相关文章:
【[STM32]标准库-自定义BootLoader】
[STM32]标准库-自定义BootLoader BootloaderBootloader的实现BOOTloader工程APP工程 Bootloader bootloader其实就是一段启动程序,它在芯片启动的时候最先被执行,可以用来做一些硬件的初始化或者用作固件热更新,当初始化完成之后跳转到对应的…...
Spring Boot项目中不使用@RequestMapping相关注解,如何动态发布自定义URL路径
一、前言 在Spring Boot项目开发过程中,对于接口API发布URL访问路径,一般都是在类上标识RestController或者Controller注解,然后在方法上标识RequestMapping相关注解,比如:PostMapping、GetMapping注解,通…...
Vue中有哪些优化性能的方法?
Vue是一款流行的JavaScript框架,用于构建交互性强的Web应用程序。在前端开发中,性能优化是一个至关重要的方面,尤其是当应用程序规模变大时。Vue提供了许多优化性能的方法,可以帮助开发人员提升应用程序的性能,从而提升…...
Python pandas遍历行数据的2种方法
背景 pandas在数据处理过程中,除了对整列字段进行处理之外,有时还需求对每一行进行遍历,来处理每行的数据。本篇文章介绍 2 种方法,来遍历pandas 的行数据 小编环境 import sysprint(python 版本:,sys.version.spli…...
Spring之@Transactional源码解析
前言 我们在日常开发的时候经常会用到组合注解,比如:EnableTransactionManagement Transactional、EnableAsync Async、EnableAspectJAutoProxy Aspect。今天我们就来抽丝剥茧,揭开Transactional注解的神秘面纱 EnableTransactionManagement注解的作用 当我们看到类似Ena…...
第三届国际亲子游泳学术峰会,麒小佑为亲游行业提供健康解决方案
第三届国际亲子游泳学术峰会大合影 2024年2月26—28日,第三届国际亲子游泳学术峰会在中国青岛成功召开。 第三届国际亲子游泳学术峰会是中国婴幼游泳行业最高标准的学术性会议,由亲游圈主办,旨在为本行业搭建一个高端圈层,帮助机…...
Python光速入门 - Flask轻量级框架
FlASK是一个轻量级的WSGI Web应用程序框架,Flask的核心包括Werkzeug工具箱和Jinja2模板引擎,它没有默认使用的数据库或窗体验证工具,这意味着用户可以根据自己的需求选择不同的数据库和验证工具。Flask的设计理念是保持核心简单,…...
C/C++ 说说引用这玩仍是干啥的
引用的本质就是给某个实例对象起个外号。生活中李逵,也叫黑旋风。诸葛亮,又叫孔明。 引用的方式: 类型& 引用名对象名 举个例子 int i0; int& ki;//这种方式就是引用----->i有了自己的小名,从次叫k了 std::cout<…...
swoole
php是单线程。php是靠多进程来处理任务,任何后端语言都可以采用多进程处理方式。如我们常用的php-fpm进程管理器。线程与协程,大小的关系是进程>线程>协程,而我们所说的swoole让php实现了多线程,其实在这里来说,就是好比让php创建了多个进程,每个进程执行一条…...
kubectl基础命令详解
管理名称空间资源 查看名称空间 [rootceshi-130 conf]# kubectl get ns [rootceshi-130 conf]# kubectl get namespace NAME STATUS AGE default Active 7d17h kube-node-lease Active 7d17h kube-public Active 7d17h kube-system …...
collection的遍历方式
增强for遍历 增强for的底层就是迭代器,为了简化迭代器的代码书写的。 他是jdk5之后出现的,其内部原理就是一个Iterator迭代器。 所有的单列集合和数组才能用增强for进行遍历。 package myCollection;import java.util.ArrayList; import java.util.C…...
SpringBoot中@Async使用注意事项
前言 Async这个注解想必大家都用过,是用来实现异步调用的。一个方法加上这个注解以后,当被调用时会使用新的线程来调用。但其实这里面也有一个坑。 问题 这个注解使用时存在如下问题:在没有自定义线程池的场景下,默认会采用Sim…...
IEEE 802.11 RTS/CTS/BA/Management
RTS/CTS IEEE 802.11 RTS/CTS即RTS/CTS协议(Request To Send/Clear To Send)即请求发送/清除发送协议是被802.11无线网络协议采用的一种用来减少由隐藏节点问题所造成的冲突的机制。 相当于一种握手协议,主要用来解决"隐藏终端"问题。"隐藏终端"(Hid…...
【风格迁移】对比度保持连贯性损失 CCPL:解决图像局部失真、视频帧间的连贯性和闪烁
对比度保持连贯性损失 CCPL:解决图像局部失真、视频帧间的连贯性和闪烁 提出背景解法:对比度保持连贯性损失(CCPL) 局部一致性假设 对比学习机制 邻域调节策略 互信息最大化对比学习:在无需标签的情况下有效学习区分…...
【C++】贪心算法
贪心算法(Greedy Algorithm)是一种基于贪心策略的算法,它在每一步选择中都采取当前状态下最优的选择,以希望最终得到全局最优解。贪心算法通常适用于满足最优子结构性质的问题,即问题的最优解可以通过其子问题的最优解…...
记一次dockerfile无法构建问题追溯
我有一个dockerfile如下: ENTRYPOINT ["/sbin/tini","-g", "--"] CMD /home/scrapy/start.sh 我原本的用意是先启动tini,再执行下面的cmd命令启动start.sh。 为啥要用tini? 因为我的这个docker…...
React使用 useImperativeHandle 自定义暴露给父组件的实例方法(包括依赖)
关键词 React useImperativeHandle 摘要 useImperativeHandle 是 React 提供的一个自定义 Hook,用于在函数组件中显式地暴露给父组件特定实例的方法。本文将介绍 useImperativeHandle 的基本用法、常见应用场景,以及如何处理其依赖项,以帮…...
yolov5v7v8目标检测增加计数功能--免费源码
在yolo系列中,很多网友都反馈过想要在目标检测的图片上,显示计数功能。其实官方已经实现了这个功能,只不过没有把相关的参数写到图片上。所以微智启软件工作室出一篇教程,教大家如何把计数的参数打印到图片上。 一、yolov5目标检测…...
JPA常见异常 JPA可能抛出的异常
1、EntityNotFoundException(实体不存在异常): 通过 JPA 查找一个不存在的实体。 2、NonUniqueResultException(非唯一结果异常): 查询返回了多个结果,但期望只有一个结果。 3、TransactionRequiredExcep…...
Dockerfile的艺术:构建高效容器镜像的指令详解与实战指南
在容器化技术风靡全球的今天,Dockerfile作为构建 Docker 镜像的蓝图,其编写技巧与理解深度直接影响着应用部署的效率与稳定性。本文将深入剖析Dockerfile中的核心指令,以实战角度为您呈现一份详尽的解读与操作指南,并在文末抛出一…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...
9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...
React核心概念:State是什么?如何用useState管理组件自己的数据?
系列回顾: 在上一篇《React入门第一步》中,我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目,并修改了App.jsx组件,让页面显示出我们想要的文字。但是,那个页面是“死”的,它只是静态…...
如何把工业通信协议转换成http websocket
1.现状 工业通信协议多数工作在边缘设备上,比如:PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发,当设备上用的是modbus从站时,采集设备数据需要开发modbus主站;当设备上用的是西门子PN协议时…...
