如何从STM32微控制器上的应用程序代码跳转到系统引导程序

1.简介


有许多可能的方法可以访问STM32设备中的系统引导程序,在本教程中,我们将介绍如何轻松地直接从我们所有系列和产品系列的应用程序代码执行此跳转,STM32F0和一些具有空检查机制的STM32L0除外。
为了实现这一目标,我们强烈建议使用以下两个主要的文档来源,以确保轻松成功地跳转。微控制器的参考手册和应用说明AN2606都包含引导加载程序的详细信息,如重要地址、支持的外围设备以及使用STM32设备自定义或系统引导加载程序时需要记住的特定要求。在应用程序说明中,可以看到说明上述系列的空检查效果的说明:

本文不会介绍擦除第一页的解决方法,但代码中会包含所有STM32s地址,以便于读者使用。我们建议阅读这篇文章,解释如何从SRAM执行代码。
假设您使用的系列允许您从应用程序跳到系统内存中,我们需要注意要执行的一些重要和必要的步骤,以及需要记住的一些注意事项:
 

1.如何查找系统内存/Bootloader启动地址值:

请参阅AN2606“系统内存引导模式中的配置”表格。每个设备都有一个特定的系统内存/Bootloader地址,必须知道该值才能正确跳转到Bootloader。
例如,对于STM32H2723ZG微控制器(此处提供了一篇显示该系列代码的快速文章),Bootloader并不是从与系统内存相同的地址开始的,但这在表111中有明确的定义。

2.禁用、卸载和清除应用程序配置的所有外围设备:

包括时钟结构、Systick定时器、ISR、外围设备初始化和GPIO,每个外围设备设置都必须设置为其默认状态,以避免系统在引导模式下中断。这就是为什么在没有合适的处理程序的情况下解编译所有这些函数并防止中断发生是最重要的。

3.重新启用中断:

清除寄存器后,在Bootloader中可以在不影响应用程序的情况下重新启用中断。
 

4.秒设置引导加载程序重置处理程序地址:

引导加载程序重置处理程序地址=引导加载程序地址+4字节偏移量。
 

5秒将主堆栈指针(MSP)设置为存储在引导加载程序堆栈中的值。

6.C所有指向系统引导加载程序的函数都开始执行。


注意:如果您的项目使用看门狗(IWDG和或WWDG),请将时基设置为可能的更高值,以避免在引导模式下重置时基。

2.发展


考虑到上面提到的所有主题,下面定义了一个通用代码,您可以根据“枚举”结构中的列表简单地设置应用程序中使用的MCU,并且该函数已准备好在您的项目中使用。
此代码的工作方式是点亮NUCLEO-H223ZG板中的一个可用用户指示灯,然后通过调用JumpToBootloader函数进入系统引导加载程序模式。
请注意,代码的所有不同部分都是专门在/*用户代码开始*/区域之间编写的,因此在重新生成项目*.ioc文件时不会擦除代码。
 
/*私有定义------------------------------------------------------------*//*用户代码开始PD*//*设置STM32微控制器系列的枚举*/enum{C0、F030x8、F030 xC、F03xx、F05、F07、F09、F10xx、F105、F107、F10XL、F2、F3、F4、F7、G0、G4、H503、H563、H573、H7x、H7A、H7B、L0、L1、L4、L5、WBA、WBX、WL、U5}#定义MCU H7x//在此处定义正在使用的MCU/*用户代码结束PD*/
/*用户代码开始PFP*/void JumpToBootloader(void);/*用户代码端PFP*/
/*无限循环*/*用户代码开始时*/WHILE(1){HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin);HAL_Delay(1000);JumpToBootloader();/*用户代码结束时*/*用户码开始时3*/}/*用户码结束时3*/
/*用户代码BEGIN 4*/void JumpToBootloader(void[F05]=0x1FFFEC00;BootAddr[F07]=0x1FFFC800;BootAddr[F09]=0x1FFFD800;BootAddr[F10xx]=0x1FFFF000;BootAddr[F105]=0x1FFFB000;BootAddr[F07]=0x1FFFB000;BootAddr[F10XL]=0x1FFFE000;BootAddr[F2]=0x1FFF0000;BootAddr[F3]=0x1FFFD800;BootAddr[F4]=0x1FFF0000;BootAddr[F7]=0x1FF00000;BootAddr[G0]=0x1FFF0000;BootAddr[G4]=0x1FFF0000;BootAddr[H503]=0x0BF87000;BootAddr[H563]=0x0BF97000;BootAddr[H573]=0x0BF97000;BootAddr[H7x]=0x1FF09800;BootAddr[H7A]=0x1FF0A800;BootAddr[H7B]=0x1FF0A000;BootAddr[L0]=0x1FF00000;BootAddr[L1]=0x1FF00000;BootAddr[L4]=0x1FFF0000;BootAddr[L5]=0x0BF90000;BootAddr[WBA]=0x0BF88000;BootAddr[WBX]=0x1FFF0000;BootAddr[WL]=0x1FFF0000;BootAddr[U5]=0x0BF90000;/*禁用所有中断*/__Disable_irq();/*禁用Systick计时器*/Systick->CTRL=0;/*将时钟设置为默认状态*/HAL_RCC_DInit();/*清除中断启用寄存器和中断挂起寄存器*/(i=0;i<5;i++){NVIC->ICER[i]=0xFFFFFFFF;NVIC->ICPR[i]=00xFFFFFFFF,}/*重新启用所有中断*/__Enable_irq();/*将跳转设置为引导加载程序地址+4*/SysMemBootJump=(void(*)(void))(*((uint32_t*)((BootAddr[MCU]+4)));/*将主堆栈指针设置为引导加载程序堆栈*/__Set_MSP(*(uint32_t*)BootAddr[MCU]);/*调用函数跳转到引导加载程序位置*/SysMemBootJump();/*跳转成功*/while(1){/*代码不应到达此循环*/}}/*用户代码结束4*/

有不同的有用方法可以测试代码是否成功工作,下面将解释其中两种方法。
 

1.秒TM32CubeIDE调试选项卡。

您可以在调试透视图左上角的调试选项卡中检查电脑是否设置为Flash或Boot地址。首先,电脑以Flash地址启动:0x08000614(对于这个特定的演示)。

进入引导加载程序后,PC现在被设置为引导区域内的地址:0x1FF127BC。点击“暂停”按钮后,您可以看到下面的选项卡。

 

2.STM32Cube编程器工具


一旦进入Bootloader区域,我们就可以使用STM32CubeProg来保证系统在系统引导模式下工作。
在本教程中,我们将使用USB入口点来执行此操作,但也可以使用给定系列的其他可用接口。请记住,USB的优先级高于其他USB,因此如果连接了电缆,它将是所选的电缆。AN2606涵盖了所有这些外围设备以及所有系列所需的设置。
注意:请注意AN2606中指定的引脚,因为即使STM32CubeIDE允许引脚重新分配,要进入引导程序,引脚必须与应用说明中的引脚相同。
要通过USB执行此操作,请连接用户USB连接器上的USB电缆。之后:

-在右角,选择USB而不是ST-LINK
-刷新端口以识别USB
-点击“连接”


连接后,搜索Bootloader的起始地址,您会看到类似于下图的内容。

您现在已经成功地从应用程序跳到了引导加载程序。干得好!
希望这篇文章能有所帮助。