IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32/GD32 Bootloader升级APP研究以及编程实现 -> 正文阅读

[嵌入式]STM32/GD32 Bootloader升级APP研究以及编程实现

一、Hex格式


【Intel英特尔Hex格式官方文档】
【什么是Hex文件格式?】


除每行开头的 ‘:’ 外,其它均是2字节表示一个十六进制数。例如02表示0x02,F2表示0xF2



在这里插入图片描述

行开头:每行以ASCII的 : 为开头
长度:标识数据区域的字节数
地址:相对于基地址的偏移地址
类型标识:有6种,如下表
数据区域
行校验: 冒号后、校验和前的值累加,并对和值按位取反后加1


数据标识定义指代本行数据类型
00数据
01文件结束
02扩展段地址。段地址始于8080CPU那个年代,现在段地址这个概念被弱化甚至尘封,忽略即可
03起始段地址
04扩展线性地址。 如上图中第1行标识了数据地址的高16位为0x0800即基地址为0x08000000,后面数据类型为数据的行的地址均为偏移地址,偏移地址都要加上基地址才能得出实际的地址,如出现下一个扩展线性地址,则表示指定新的基地址
05起始线性地址。 告诉单片机从哪个地址开始运行程序




在Keil MDK中更改程序起始地址 0x8000000 -> 0x8005000 后, hex文件的地址变化如下:

在这里插入图片描述


二、烧写地址设置


在Keil MDK中,对Cortex-M3/4已经默认了程序烧录起始地址是0x08000000,并且可以选择在烧写程序前进行全片擦除或是按需擦除 。那么就可以划分出两块区域分别放Bootloader程序和APP程序。


在这里插入图片描述
在这里插入图片描述


例如如下划分

StartSize
Bootloader0x80000000x5000 (20K)
APP0x80050000x78000 (492K)
或者
APP0x80000000x78000 (492K)
Bootloader0x80780000x5000 (20K)

Bootloader在前:单片机上电时先运行Bootloader,等待升级指令。无指令时计时,超时进入APP;有升级指令,则开始升级APP即接收升级数据写入Flash,写入完成后跳转APP。
Bootloader在后:单片机上电时直接进入APP,运行过程中接收到升级指令后跳转Bootloader进行APP升级。升级完成后跳转APP。
同样的,在APP中也可升级Bootloader,但一般不需要。
Bootloader的功能尽量单一,大小尽量小,且占用的地址不能与APP的重叠。


需要特别注意的是,如果不勾选“Use Memory Layout from Target Dialog”,则上面选项卡中设置的地址是不起作用的,需要自行修改分散加载文件(未研究)。


在这里插入图片描述

在这里插入图片描述


三、Bootloader跳转APP代码


跳转前需要检查APP的栈顶指针是否合法、关闭所有中断、重设栈顶指针、偏移中断向量表(可以在APP中设置)。

定义如下数据

#define APP_LOADED_ADDR						0x5000		//APP加载地址
typedef  void  (*pAppFunction) (void);
pAppFunction application;
__IO uint32_t JumpAddress = NULL;

升级APP完成后,调用如下代码

/* APP栈顶指针合法 */
if (0x20000000 == ((*(__IO uint32_t*)APP_LOADED_ADDR) & 0x2FFE0000))
{
	__disable_irq();	//关闭所有中断
	JumpAddress = *(__IO uint32_t*)(APP_LOADED_ADDR + 4);	//Reset_Handler 入口地址
	application = (pAppFunction) JumpAddress;
	__set_MSP(*(__IO uint32_t*) APP_LOADED_ADDR);	//APP程序堆栈指针起始
	printf("APP地址%#x, \r\n", APP_LOADED_ADDR);
	application();	//跳转到Reset_Handler即APP
}
  • 宏 APP_LOADED_ADDR 是APP的起始地址,而APP程序的起始是栈顶指针。
  • 为什么加载地址不是0x8005000?
    因为选择了从Flash启动,所以Flash被映射到了0x00000000。所以访问0x080050000和0x5000效果是一样的。
  • 所以如果正确写入了APP,则 地址 (__IO uint32_t *)APP_LOADED_ADDR 处的栈顶指针必然在该型号单片机的SRAM大小范围内。96K Sram地址范围为0x2000 0000 - 0x2001 7FFF,64K Sram地址范围为0x2000 0000 - 0x2000 FFFF。
  • (0x20000000 == (((__IO uint32_t)APP_LOADED_ADDR) & 0x2FFE0000)) 表示的是从地址0x5000取出栈顶指针,通过运算检查栈顶地址是否落在0x2000 0000 - 0x2001 7FFF。64K的检查为(0x20000000 == (((__IO uint32_t)APP_LOADED_ADDR) & 0x2FFF0000))。相当于读出的值直接与Sram范围值比较。
  • 跳转到APP不是跳转栈顶指针,而是跳转Reset_Handler,而Reset_Handler在栈顶指针后,所以需要偏移32位。
  • application为一个void类型的函数指针,并将其指向Reset_Handler的地址。application()表示执行指针指向的函数,即Reset_Handler函数。
  • 跳转前关闭中断,防止 1)已经跳转到APP了但来了一个中断并落在了Bootloader, 2)中断向量表已偏移但来了中断,就会落在错误的地方

需要特别注意的是,如果使能了Systick等内核级别的中断,用__disable_irq(); 之类的屏蔽中断的语句是无法关闭的,需要去停止Systick的运行。最优的是在bootloader跳转前关闭所有用到的资源以及中断,在APP中重新配置所需要的,以免在Bootloader中用到的中断在APP中没有用到,而缺少对应的中断处理导致中断死循环或HardFault。



四、APP中的处理


/* 基地址 */
#define NVIC_VECTTAB_RAM            ((uint32_t)0x20000000) /*!< RAM */
#define NVIC_VECTTAB_FLASH          ((uint32_t)0x08000000) /*!< Flash */

/* NVIC中断向量表偏移掩码 */
#define NVIC_VECTTAB_OFFSET_MASK    ((uint32_t)0x1FFFFF80)

#define USER_BOOT_EXIST						1			//是否有bootloader
#define VECT_TAB_OFFSET						0x5000		//

#if (USER_BOOT_EXIST == 1)
	/* APP中断向量表地址偏移 需要在Linker选项卡勾选“USE Memory Layout from Target Dialog”,并修改Target选项卡中的ROM的Start地址 */
	nvic_vector_table_set(NVIC_VECTTAB_FLASH, VECT_TAB_OFFSET);
	__enable_irq();	//解除中断屏蔽
#endif

void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset)
{
    SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK);
}
  • 如果在Bootloader跳转APP前就设置了中断向量偏移,则略过。
  • NVIC_VECTTAB_OFFSET_MASK掩码为0x1FFFFF80是因为VTOR寄存器的格式在这里插入图片描述
  • APP地址偏移不能随意,CortexM3 M4权威指南中有如下描述。且还要关注该型号单片机的Flash每页大小,因为写Flash时需要整页擦除,须避免APP和Bootloader代码在同一页。

在这里插入图片描述

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-28 12:02:29  更:2022-04-28 12:02:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:19:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码