STM32H7之系统bootLoader一章搞定


STM32 的系统存储区自带 bootloader,此程序是 ST 在芯片出厂时烧录进去的,主要用于将用户应用程序下载到芯片内部 Flash。支持 USB,SPI,I2C,CAN,UART 等接口方式下载。如果大家的应用程序打算采用这种接口方式进行升级,可以考虑采用系统 bootloader,简单易用,无需用户自己写bootLoader 了。
但是该方式的局限性还是比较大,无法自己对bootLoader进行更多的操作,仅仅是能够通过STM32自己的方式进行升级而已。

系统bootLoader的执行流程

在这里插入图片描述
关于这个执行流程,要特别注意一点:如果在进入系统 BootLoader 前就插入了 USB 线,会导致进入系统 BootLoader 后优先执行 USB DFU,其它的接口方式将没有机会执行。

系统bootLoader使用的引脚

STM32H7 的 Bootloader 使用到的引脚分配如下:
在这里插入图片描述

进入系统bootLoader的方法

通过boot引脚进入系统bootLoader

H7 的启动方式比较更灵活,只需一个 boot 引脚。但是一个引脚只能区分出两个状态,为了解决这个问题,H7 专门配套了两个 option bytes 选项字节配置,如此以来就可以方便设置各种存储器地址了。
在这里插入图片描述
BOOT_ADD0 和 BOOT_ADD1 对应 32 位地址到高 16 位,这点要特别注意。通过这两个选项字节,
所有 0x0000 0000 到 0x3FFF 0000 的存储器地址都可以设置,包括:
◆ 所有 Flash 地址空间。
◆ 所有 RAM 地址空间,ITCM,DTCM 和 SRAM。
设置了选项字节后,掉电不会丢失,下次上电或者复位后,会根据 BOOT 引脚状态从 BOOT_ADD0,或 BOOT_ADD1 所设置的地址进行启动。也就是说是,H7 可以从 0x0000 0000 到 0x3FFF 0000 所有地址进行启动,这点与 F4 完全不同,F4 系列是固定从 0x0000 0000 启动的。
STM32H7 的 boot 引脚设计:
在这里插入图片描述
如果用户不慎,设置的地址范围不在有效的存储器地址,那么 BOOT = 0 时,会从 Flash 首地址0x0800 0000 启动,BOOT = 1 时,会从 ITCM 首地址 0x0000 0000 启动。
如果用户使能了 Flash Level 2 保护,那么只能从 Flash 地址空间进行启动。

通过用户程序跳转到系统bootLoader

除了使用 boot 引脚控制运行系统 BootLoader,也可以上电后跳转,跳转前注意以下问题:
◆ 禁止所有外设时钟。
◆ 禁止使用的 PLL。
◆ 禁止所有中断。
◆ 清除所有中断挂起标志。
◆ 如果使用 Go 命令,对于 BootLoader 中使用的硬件外设寄存器,跳转前是不会设置到复位值的,如果用户代码中恰好也用到这些寄存器,需要重新配置。这里要特别注意的是 BootLoader 会用到看门狗,并且喂狗时间设为最长了,如果用户代码里面要用到看门狗请根据需要重新配置,并且看门狗一旦开启是无法关闭的。
◆ 对于具有双 bank 特性的 STM32,为了能够从用户代码跳转到系统 boot,需要将系统 boot 代码区使用寄存器 SYSCFG 重映射到 0x0000 0000(除了 F7 和 H7 系列)。对于 STM32F7 系列,需要禁止 nDBOOT / nDBANK 特性,然后跳转到系统 boot 区。
◆ 如果用到系统 bootloader 的 DFU/CAN 接口,需要用到 HSE 时钟,这个时钟的频率是通过内部HSI/MSI 检测出具体频率。因此,由于外部温度等各种情况,内部 HSI 的精度会受到影响,从而影响检测出来的 HSE 时钟有较大误差,最终导致 DFU/CAN 运行失败。

/*
******************************************************************************************************
* 函 数 名: JumpToBootloader
* 功能说明: 跳转到系统 BootLoader
* 形 参: 无
* 返 回 值: 无
******************************************************************************************************
*/
 static void JumpToBootloader(void)
{
uint32_t i=0;
void (*SysMemBootJump)(void); /* 声明一个函数指针 */
 __IO uint32_t BootAddr = 0x1FF09800; /* STM32H7 的系统 BootLoader 地址 */

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

/* 关闭滴答定时器,复位到默认值 */
SysTick->CTRL = 0;
SysTick->LOAD = 0;
 SysTick->VAL = 0;
/* 设置所有时钟到默认状态,使用 HSI 时钟 */
HAL_RCC_DeInit();

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

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

 /* 跳转到系统 BootLoader,首地址是 MSP,地址+4 是复位中断服务程序地址 */
SysMemBootJump = (void (*)(void)) (*((uint32_t *) (BootAddr + 4)));

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

 /* 在 RTOS 工程,这条语句很重要,设置为特权级模式,使用 MSP 指针 */
 __set_CONTROL(0);
/* 跳转到系统 BootLoader */
 SysMemBootJump(); 

这里把程序设计中的几个关键地方做个说明:
◆ 第 12 行,声明一个函数指针。
◆ 第 13 行,这个要特别注意,H7 的系统 Bootloader 地址在 0x1FF09800。
◆ 第 19 到 21 行,设置滴答定时器到复位值。
◆ 第 24 行,此函数比较省事,可以方便的设置 H7 所有时钟到复位值,内部时钟使用 HSI。
◆ 第 27 到 31 行,清除所有中断挂起标志并关闭中断,这里是直接通过一个 for 循环设置了 NVIC 所有配置位,共 8 组。
在这里插入图片描述
◆ 第 37 行,将系统 bootLoader 的中断复位服务程序的入口地址赋给第 12 行声明的函数,用户执行这个函数时,就会直接跳转过去。
◆ 第 40 行,设置主堆栈指针位置,即系统 bootloader 的首地址存储的就是栈地址。
◆ 第 43 行,这个设置在 RTOS 应用程序中比较重要,因为基于 Cortex-M 内核的 RTOS 任务堆栈基本都是使用线程堆栈指针 PSP。但系统bootLoader 使用的是主堆栈指针 MSP,所以务必要设置下,同时让 M 内核工作于特权级。此寄存器的作用如下:
在这里插入图片描述
◆ 第 46 行,跳转到系统 bootLoader。

系统bootLoader的擦写管理

使用 bootloader 命令进行的所有写操作都只能字对齐(地址应该是 4 的倍数)。要写入的数据数量也必须是 4 的倍数(接受未对齐的半页写地址)。

◆ 有些产品不支持批量擦除操作。使用 BootLoader 进行批量擦除时,有两种方法可用:
使用扇区擦除命令一个一个删除。
将保护级别设置为 1,然后设置为 0(使用读保护命令,然后使用读非保护命令),将导致大批量擦除操作。

◆ STM32 L1 和 L0 系列的 Bootloader 除了支持操作内部 Flash,内部 SRAM,可选字节等,还支持操作 Data Memeory(数据存储区,貌似是指的 EEPROM)。数据存储区支持读写操作,而不支持擦除命令,如果要擦除,写 0 即可。另外对此存储区的写操作必须是 4 字节对齐(写地址),并且写入的数据也是 4 的倍数。

◆ F2, F4, F7 和 L4 除了支持操作内部 Flash,内部 SRAM,可选字节等,还支持操作 OTP 存储区。仅支持读写操作,不支持擦除命令。

◆ F2, F4 和 F7 系列的内部 Flash 写格式依赖于供电电压范围,默认的写操作只支持字节(半字,字和双字是不支持的),为了增加写操作速度,用户施加足够的电压范围以允许写操作按半字,字或双字,并通过虚拟内存位置的 boot 程序更新此配置。该内存位置不是物理地址,但可以根据协议使用常规的 BootLoader 读写操作。该存储位置包含 4 个字节,分别为如下表所述:
在这里插入图片描述

  • 11
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值