设计一款STM32的BootLoader

2023-05-16

参考文章:https://blog.csdn.net/qingtian506/article/details/9128899

之前很想做一个属于STM32的BootLoader,但是想想没什么实际用处就没有下手,但是当前的项目遇到的麻烦事情要我改变了这种看法。比如说我开发了一个产品需要测试,把一个样品送到客户手里去测试使用,但是客户在使用的过程中提出了一些修改建议,那我就在做一个样品改好程序之后发出去给客户,不久之后客户又有了新的修改要求,如此往复,大部分时间都耽误在做样品、寄快递上了,极大地耽误了产品的研发周期。但是如果我们能够远程的将修改好的程序下载到产品上去的话会减少很多研发时间。当然前提是产品本身有接出来通信接口,我们使用这个接口才能进行程序升级,或者产品本身能够连接到网络通过网络更新固件。

好的,既然BootLoader是有实际价值的,那就能动手。首先要理解BootLoader是什么东西,这个是源自linux上的BootLoader的概念,在linux上,BootLoader是首先执行的程序,BootLoader启动之后初始化CPU、RAM、Flash等设备,然后从Flash中读取Linux程序数据到RAM中去,最后跳转到RAM中Linux的起始地址中去启动Linux系统。除了从Flash中读取系统启动之外,BootLoader还能通过网络NFS协议从服务器上读取Linux并启动。BootLoader还能够更新Linux内核、配置Linux启动信息、测试系统等等。我们要做的STM32的BootLoader也是类似的工作原理,但是没有Linux系统的BootLoader功能那么强大。我们要做的STM32的BootLoader只有两个主要目的:

1、跳转到应用程序并执行。

2、更新应用程序。

为了实现上面的两个基础功能我们创建两个工程一个叫probooter一个叫proapp,前者是BootLoader程序工程,后者是测试用的应用程序。

我们需要规定好BootLoader和Application程序再Flash中的存储结构,我们使用的是64KB Flash的STM32进行测试,BootLoader程序占用前20KB的空间,Application占用后面的43KB的空间,最后1KB的空间不能使用,好像是用来标志Flash锁定状态的,忘了是我之前用的其他MCU上规定的的还是STM32上的规定,反正也不差这个1KB。Flash存储结构如下:

0x0800 0000	page0 	BootLoader程序起始地址
.		page1 
.		page2 
 		......
.		page18
.		page19
0x0800 5000	page20	Application程序起始地址
.		page21
.		page22
 		......
.		page60
.		page61
.		page62	Application程序终止地址
0x0801 0000	page63	Flash存储器终止地址(根据型号不同有变) 同时用于存储APP程序的CRC数据

我们需要根据上面的存储结构配置BootLoader工程和Application工程。

BootLoader工程配置如下:

ROM起始地址为0x08000000,大小为0x5000。

 

程序存储基地址为0x08000000,RAM存储基地址为0x20000000。

 

Jlink下载配置器件的Start地址为0x08000000,size为0x5000。

 

 

 

Application工程配置如下:

ROM起始地址为0x08005000,大小为0x10000,这个大小大点没关系,但是BootLoader的大小必须严谨。

 

最重要的地方!!!这里的R/O Base一定要写0x08005000,表示程序基地址为0x08005000,所有函数、常量数据的地址以这个为基地址。R/W Base还是0x20000000,。

 

Jlink下载配置器件的Start地址为0x08005000,size为0x10000。

 

配置好了两个工程之后在Application工程中里写测试程序例如:

int main(void)
{
	Initialization();
	debug("123456789\r\n");
	int i = 0;
	while(1)
	{
		debug("%d ",i++);
		delay_ms(100);
	}
}

然后通过MDK使用Jlink下载程序,发现无法运行。这是对的,因为程序存放在了0x08005000处,单片机复位的时候从0x08000000(默认向量表存放位置)处获取复位向量,而0x08000000处是空的没有数据(假设一开始单片机被整片擦除了),这样程序就跑飞了。

 

下面来写BootLoader程序,简单测试一下,将Application程序复制过来,编译下载之后程序可以运行,因为BootLoader程序的存放地址就是放在0x08000000处的,故可以正常运行。接下来可以测试一下从BootLoader程序跳转到Application程序运行。我本来以为可以使用汇编跳转指令“B”来实现跳转:

	__asm("B 0x08005004");

但是发现这个指令不能使用,编译器直接忽略了这个指令了,我也忘了ARM汇编指令,而且这个是Thumb-2指令,算了换一个实现方法:使用函数指针跳转。

首先要获取Application程序的复位中断向量,查看Cortex M3权威指南中写道:

可以看出来复位向量在向量表的第二个字中,那我们读取0x08005004处的一个字的数据就是复位函数的入口地址。

	void (*p)(void) = (void (*)(void))(*((int*)0x08005004));

上面这段程序就能将函数指针p指向Application程序的复位函数。

得到了Application程序的复位函数之后我们还不能急着跳转到Application程序中去,因为我们前面有提示,默认的中断向量表是在0x08000000处,而0x08000000处的中断向量表是BootLoader的,而不是Application的,我们需要重定位中断向量表,这个在权威指南中也有说明:

.

中断向量表是可以设置的,STM32也实现了Cortex-M的这个功能,可以调用NVIC_SetVectorTable函数:

	NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x08005000);

修改了中断向量表之后就可以跳转到Application程序的复位函数中去了:

	p();

实验结果的确是可以跳转到Application中去执行,我们已经完成了我们要开发的BootLoader的第一个功能:跳转到应用程序并执行。

下面还要实现BootLoader的第二个功能,就是更新Application程序。更新Application程序其实很简单,调用库函数中的Flash操作函数既可以。需要注意的是要先擦除Flash页之后才能向Flash中写数据。并且无论是擦除还是写入数据到Flash,都要先进行Flash解锁操作(FLASH_Unlock),擦除或者写入到Flash完成之后进行Flash锁定操作(FLASH_Lock)。同时在操作Flash之前要清除标志位(FLASH_ClearFlag),防止之前发生的标志位影响下面的操作。

Flash的擦写实现起来很简单,还有一个重点问题是如何获取Application程序数据,假设我们使用一个串口通信,这时候需要使用一个PC端的配套下载软件将程序文件下载到MCU中,BootLoader程序要接收到程序文件并且将程序文件写入到正确的Flash地址中去。

为了方便起见,我使用X-Modem协议,串口通信中这个协议使用的比较多,具体可以参考:https://blog.csdn.net/mcgrady_tracy/article/details/14522263、https://blog.csdn.net/m0_37756916/article/details/76064727两篇文章。

当可以正确接收到程序文件并且正确的存放到Flash中去的话就可以跳转到Application程序了,下面是我的实验结果:

执行顺序是线擦除Application空间的Flash,然后调用Xmodem协议将程序文件下载并写入到Flash中去,最后跳转到Application程序的复位函数中执行。

这里要注意的是MDK生成的HEX文件是不能下载的,需要转换成BIN文件,网上有很多HEX转BIN的工具,转换之后得到的BIN文件也不是能够直接下载的,因为生成的BIN文件是从0x08000000处开始的,为什么不是直接从0x08005000处开始呢,因为使用其他的串口下载工具下载的时候需要从头开始下载,而不是从0x08005000处开始下载,我这里是特殊应用,所以需要先删除0x08005000前面的数据,得到一个可以直接存放0x08005000处的文件。测试的时候可以自己使用winhex删除。

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计一款STM32的BootLoader 的相关文章

  • STM32F103

    提示 来源正点原子 参考STM32F103 战舰开发指南V1 3PDF资料 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 开发环境硬件普中科技 接线图在g
  • STM32 GPIO工作原理详解

    STM32 GPIO介绍 1 STM32引脚说明 GPIO是通用输入 输出端口的简称 是STM32可控制的引脚 GPIO的引脚与外部硬件设备连接 可实现与外部通讯 控制外部硬件或者采集外部硬件数据的功能 以STM32F103ZET6芯片为例
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • VS Code 有没有办法导入 Makefile 项目?

    正如标题所说 我可以从现有的 Makefile 自动填充 c cpp properties json 吗 Edit 对于其他尝试导入 makefile 的人 我找到了一组脚本 它们完全可以实现我想要实现的目标 即通过 VS Code 管理
  • 加载引导加载程序的第二阶段和/或将控制权转移给它时出现问题

    我的主引导记录代码 bit16 16bit by default org 0x7c00 jmp short start nop bsOEM db OS423 v 0 1 OEM String start cls mov ah 06h Fun
  • UEFI引导加载程序

    我正在考虑开发一个简单的 首先 UEFI 引导加载程序来加载 ELF 映像 并且想知道是否有人有一个很好的切入点 可以进入任何现有项目 或者我可以用来开始使用的示例 另外 我想知道是否有人有让虚拟机运行 EFI 应用程序的经验 我已经设置了
  • 与 CMPSB 指令混淆

    我一直在看这段代码 我对代表 cmpsb line LOOP push cx mov cx 0x000B eleven character name mov si ImageName image name to find push di r
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • STM32的HAL中实现单按、长按和双按功能

    我正在尝试实现单击 双击和长按功能来执行不同的功能 到目前为止 我已经理解了单击和长按的逻辑 但我不知道如何检测双击 至于代码 我使用计数器实现了单击和长按 但代码仅停留在第一个 if 条件上 bool single press false
  • STM32F207 I2C 测试失败

    我正在使用 STM32F207 微控制器在 STM3220G EVAL 板上学习嵌入式开发 我尝试通过连接同一芯片上的两个 I2C2 和 I2C3 模块并发送 接收字符来测试 I2C 接口 这是我当前编写的代码 使用 mdk arm 5 i
  • 无法使用 OpenOCD 找到脚本文件

    我正在尝试按照本教程将 OpenOCD 与我的 ST 发现板一起使用 https japaric github io discovery README html https japaric github io discovery READM
  • CMSIS & STM32,如何开始? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 STM32 上使用 CMSIS 启动项目 网上一搜 没找到具体的教程 有些使用 SPL 开始项
  • 库函数点亮Led

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 例如 随着人工智能的不断发展 机器学习这门
  • 通过JTAG恢复STM32 MCU磨掉的标记

    我有一块可能带有 STM32 MCU 的板 我想为该板制作定制固件 因为库存板有很多问题 不幸的是 电路板制造商很友善地磨掉了所有标记 有没有办法通过 jtag 获取设备 系列 ID 并将其交叉引用到型号 我能找到的一切都是关于获取芯片的唯
  • 使用 int 13h 读取的扇区数量多于磁道上的扇区数量

    顺序是什么int 13h with ah 02h会读19部门起始于 C H S 0 0 1 提供了 2 个磁头 每磁道 18 个扇区 每面 80 个磁道的 软盘 磁盘几何结构 或者 更一般地说 当它到达磁道 0 的末尾 磁头 0 时会发生什
  • 是否有 FAT FS 驱动程序希望引导扇区的字节 508 和 509 为零?

    在实施的同时我自己的引导扇区加载程序从 2012 年开始 https hg ulukai org ecm ldosboot rev 17884e6352e6 l1 255我确保将偏移量 508 和 509 处的字节清零 这些是标准 512
  • STM32 上的位置无关代码 - 指针

    我已成功在 STM32 上构建并运行位置无关的代码 向量表和 GOT 已修补 一切正常 但我对这样的代码有问题 double myAdd double x return x 0 1 double ptrmyAdd double myAdd
  • 当端点和 PMA 地址均更改时,CubeMX 生成的 USB HID 设备发送错误数据

    我正在调试我正在创建的复合设备的问题 并在新生成的仅 CubeMX 代码中重新创建了该问题 以使其更容易解决 我添加了少量代码main 让我发送 USB HID 鼠标点击 并在按下蓝色按钮时使 LED 闪烁 uint8 t click re
  • STM32 传输结束时,循环 DMA 外设到存储器的行为如何?

    我想问一下 在以下情况下 STM32 中的 DMA SPI rx 会如何表现 我有一个指定的 例如 96 字节数组 名为 A 用于存储从 SPI 接收到的数据 我打开循环 SPI DMA 它对每个字节进行操作 配置为 96 字节 是否有可能

随机推荐

  • kubernetes dashboard用户界面安装使用

    原文 xff1a https www toocruel net kubernetes dashboardyong hu jie mian an zhuang shi yong 1 下载kubernetes dashboard yaml文件
  • 网络通信编程学习笔记(四):在Ubuntu下创建新用户、用puTTY/VNCViewer远程登录、用ftp上传和下载、用Xming远程连接

    前言 真的用不惯VNCViewer xff0c 树莓派还是外接显示屏来的舒服 xff0c 分辨率也是1080p xff0c 只有全高清壁纸才可以慰籍学习之痛 xff01 Xming也是不如按开机键来的方便 笑哭 目录 一 用puTTY VN
  • node.js和npm离线安装

    离线安装node js和npm 1 下载官方安装包并拷贝到离线机器上 官方下载地址 xff1a https nodejs org en download 2 解压文件 xff1a tar xJf node v8 9 4 linux x64
  • Github 创建新分支

    一 clone Repository clone Github 上的Repository xff0c 如下 xff1a git clone git 64 github span class hljs preprocessor com spa
  • ARM平台基于嵌入式Linux部署ROS

    By Toradex 秦海 随着ARM平台处理能力的日益强大 xff0c 越来越多的工业智能 机器人应用在ARM平台上面实现 xff0c 在这个过程中不可避免的就涉及到将机器人应用开发框架移植到ARM平台来运行 xff0c 因此本文就着重示
  • 如何设计一款低成本的计算机载板- 第一部分

    By Toradex Peter Lischer 1 简介 在以前的博客文章中 xff0c 我们已经在一个硬件项目中使用计算机模块提出了许多讨论 xff0c 因此 xff0c 这里我们假设你已经在项目中决定采用计算机模块SoM xff0c
  • git rebase后commit id的变化

    经测试发现 xff0c 在执行完 git rebase 之后 xff0c 1 xff09 会生成的新的 commit id 2 xff09 新 commit 与旧 commit 的父节点不相同 3 xff09 旧 commit 的父节点保持
  • 嵌入式Linux下串口调试

    By Toradex秦海 1 简介 UART串口是嵌入式设备最为常用的调试和通讯接口之一 xff0c 无论是RS232还是RS422 485都有着非常广泛的应用 xff0c 因此本文就基于嵌入式Linux演示在User Space进行串口调
  • [LeetCode刷题笔记] 关于LeetCode的前言

    原创文章 转载请注册来源http blog csdn net tostq 又到了一年毕业就业季了 xff0c 三年前的校招季我逃避了 xff0c 可这一次终于还是要轮到我了 61 61 作为要准备踏入码农行业的人来说 xff0c 要准备校招
  • 关于机器视觉标定的pnp问题

    https blog csdn net cocoaqin article details 77485436 https blog csdn net cocoaqin article details 77848588利用二维码求解相机世界坐标
  • kvaser在linux中的应用

    本文主要讲解 xff0c kvaser如何使用简单socketcan 1 硬件 kvaser USBcan Pro 2xHS v2 2 准备系统 ubuntu 16 04 由于项目需要在程序中使用socketcan xff0c 所以需要将k
  • 编译错误-build stopped: subcommand failed. 解决方法

    make 1 Leaving directory 96 home sunhz sl8541e out target product sp8541e srvm obj u boot15 39 make Leaving directory 96
  • 如何备份jetson nano 的u盘系统?

    使用工具 xff1a Win32DiskImager 备份步骤 xff1a 1 在本地盘 xff08 C盘或D盘都行 xff0c 盘符剩余内存大于u盘系统内存就行 xff09 新建文本文档 xff0c 连后缀名字一起改成backup img
  • Security Onboard Communication-SecOC

    一 通讯加密的必要性 随着汽车电子的发展及整车功能复杂性的提高 xff0c 车载控制器数量从之前的寥寥几个增加至规模复杂的上百个 基于功能的需求 xff0c 各个控制器每时每刻需要进行大量数据的交互 xff0c 数据交互的方式也多种多样 x
  • 解决VNC远程连接树莓派,窗口显示不全的问题,亲测可行!!

    哇 xff0c 就在刚刚才百度到解决VNC远程连接树莓派 xff0c 窗口显示不全的问题 xff0c 昨晚上查了一晚上都没搞定 xff0c xff0c xff0c 首先说下问题吧 xff0c 就是用VNC远程连接树莓派后 xff0c 会出现
  • Avoid mutating a prop directly since the value will be overwritten whenever

    在vue中 父组件向子组件传值 并在子组件改变了父组件的值 就会发出警告 所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定 xff1a 父级 prop 的更新会向下流动到子组件中 xff0c 但是反过来则不行 这样会防止
  • 【Linux】异步网络库dyad代码阅读

    简介 dyad是一个基于C编写的异步网络库 xff0c 非常精简 xff0c 单C文件 xff0c 仅实现TCP xff0c 很适合用来学习Linux网络编程和异步非阻塞处理 链接 Github链接 基于Dyad的echo server实现
  • 明文签署文件不可用,结果为‘NOSPLIT’

    快速记录一下在 debian上使用 apt update时遇到的一个小问题 明文签署文件不可用 xff0c 结果为 NOSPLIT xff08 您的网络需要认证吗 xff1f xff09 报错现场如下所示 xff1a span class
  • Ubuntu 16.04 安装 Gazebo

    Gazebo 是一款 3D 动态模拟器 xff0c 能够准确有效地模拟复杂室内和室外环境中的机器人群体 虽然类似于游戏引擎 xff0c Gazebo 提供了更高保真度的物理模拟 一套传感器以及用户和程序接口 Gazebo 的典型用途包括 x
  • 设计一款STM32的BootLoader

    参考文章 xff1a https blog csdn net qingtian506 article details 9128899 之前很想做一个属于STM32的BootLoader xff0c 但是想想没什么实际用处就没有下手 xff0