通过应用程序跳转到STM32中的Bootloader,即在用户闪存的引导模式下使用Boot 0和Boot 1 Pins

Jas*_*ora 7 c usb stm32 dfu

我有固件升级的要求.我打算使用USB DFU类.但在我的情况下,固件升级命令将来自PC应用程序.所以我需要切换到系统内存中的bootloader.最初我正在运行应用程序,因此它从用户闪存启动,即我为用户闪存配置了Boot0和Boot 1引脚.由于DFU引导加载程序存在于系统闪存中,现在需要更改Boot0和Boot1引脚设置.有没有像启动0和启动1设置保持用户闪存相同的方式,在应用程序中我们跳转到系统内存?

小智 22

Boot0/1引脚仅在处理器启动时被采样,以检查它是否应从内存加载用户代码或是否应加载引导加载程序.之后这些引脚的状态对引导加载程序没有影响.

我一直面临类似的请求,并找到了2种按需加载引导加载程序的方法.

首先,您可以从用户代码到引导加载程序"JUMP".例如,您可以在按下按钮时跳转到引导加载程序.

但是......这比简单的JUMP指令复杂得多:一些寄存器和设备必须正确配置才能与引导程序一起工作,你必须确保在JUMP期间不会触发IRQ,...实际上,你必须重新配置处理器,就像它在重置后刚启动一样.您可以在此视频中找到有关此技术的一些信息.

我设法在STM32F1xx项目上做了这样的事情.然而,在基于STM32F4的更复杂的项目中,这将变得非常困难......我将不得不停止所有设备(定时器,通信接口,ADC,DAC ......),确保不会触发IRQ,重新配置所有时钟,......

相反,我决定实现第二个解决方案:当我想跳转到引导加载程序时,我在其中一个备份寄存器中写入一个字节,然后发出软复位.然后,当处理器重新启动时,在程序的最开始,它将读取该寄存器.该寄存器包含指示应在引导加载程序模式下重新引导的值.然后,跳转到引导加载程序要容易得多,如YouTube视频中所示.

  • @JF002 两个视频链接都是一样的。 (2认同)

j12*_*567 6

您可以模拟引导加载程序条件。将电容器和并联电阻从 BOOT 引脚连接到地。将另一个空闲引脚连接到 BOOT 引脚。电容可由外部引脚充电,由电阻放电。我不记得您可以计算/实验它们的确切值(重要的是 RC 电路的时间常数)。

通过将外部引脚设置为 1 为该电容器充电,通过 执行软件复位NVIC_SystemReset。重置后,它将运行引导加载程序。电阻连接到电容器将执行放电。固件更新后,您可以重置设备,它将运行到您的应用程序。

我们在一些应用程序中使用它,它运行良好。这种解决方案的缺点是需要外部电路,但实现起来非常容易,并且对所有STM32设备都是通用的。


Dav*_*nds 5

在MicroPython中,有一个pyb.bootloader()函数用于进入DFU模式。

在其源存储库中找到的实现的C代码。

我已经广泛使用了STM32F4版本(#else方块)和F7变体了几次(尽管已经有一段时间了)。

我将函数的主体放在此处,因为如果该文件发生更改,上述链接可能会过时:

// Activate the bootloader without BOOT* pins.
STATIC NORETURN mp_obj_t machine_bootloader(void) {
    pyb_usb_dev_deinit();
    storage_flush();

    HAL_RCC_DeInit();
    HAL_DeInit();

#if defined(MCU_SERIES_F7)
    // arm-none-eabi-gcc 4.9.0 does not correctly inline this
    // MSP function, so we write it out explicitly here.
    //__set_MSP(*((uint32_t*) 0x1FF00000));
    __ASM volatile ("movw r3, #0x0000\nmovt r3, #0x1FF0\nldr r3, [r3, #0]\nMSR msp, r3\n" : : : "r3", "sp");

    ((void (*)(void)) *((uint32_t*) 0x1FF00004))();
#else
    __HAL_REMAPMEMORY_SYSTEMFLASH();

    // arm-none-eabi-gcc 4.9.0 does not correctly inline this
    // MSP function, so we write it out explicitly here.
    //__set_MSP(*((uint32_t*) 0x00000000));
    __ASM volatile ("movs r3, #0\nldr r3, [r3, #0]\nMSR msp, r3\n" : : : "r3", "sp");

    ((void (*)(void)) *((uint32_t*) 0x00000004))();
#endif

    while (1);
}
Run Code Online (Sandbox Code Playgroud)

pyb_usb_dev_deinit()函数关闭USB,并且storage_flush写入所有缓存的文件系统数据。HAL函数来自STM32Cube HAL文件。

如果使用较新版本的dfu-util(IIRC 0.8或更高版本),则可以指定-s :leave命令行选项,以在刷新结束时执行新刷新的程序。结合以上所述,我无需触摸板就经历了刷新/测试周期,并且仅在固件严重崩溃时才使用BOOT0 / RESET。

还有一个名为pydfu.py的python DFU刷新器:https : //github.com/micropython/micropython/blob/master/tools/pydfu.py,它比dfu-util快一点。