小智 22
Boot0/1引脚仅在处理器启动时被采样,以检查它是否应从内存加载用户代码或是否应加载引导加载程序.之后这些引脚的状态对引导加载程序没有影响.
我一直面临类似的请求,并找到了2种按需加载引导加载程序的方法.
首先,您可以从用户代码到引导加载程序"JUMP".例如,您可以在按下按钮时跳转到引导加载程序.
但是......这比简单的JUMP指令复杂得多:一些寄存器和设备必须正确配置才能与引导程序一起工作,你必须确保在JUMP期间不会触发IRQ,...实际上,你必须重新配置处理器,就像它在重置后刚启动一样.您可以在此视频中找到有关此技术的一些信息.
我设法在STM32F1xx项目上做了这样的事情.然而,在基于STM32F4的更复杂的项目中,这将变得非常困难......我将不得不停止所有设备(定时器,通信接口,ADC,DAC ......),确保不会触发IRQ,重新配置所有时钟,......
相反,我决定实现第二个解决方案:当我想跳转到引导加载程序时,我在其中一个备份寄存器中写入一个字节,然后发出软复位.然后,当处理器重新启动时,在程序的最开始,它将读取该寄存器.该寄存器包含指示应在引导加载程序模式下重新引导的值.然后,跳转到引导加载程序要容易得多,如YouTube视频中所示.
您可以模拟引导加载程序条件。将电容器和并联电阻从 BOOT 引脚连接到地。将另一个空闲引脚连接到 BOOT 引脚。电容可由外部引脚充电,由电阻放电。我不记得您可以计算/实验它们的确切值(重要的是 RC 电路的时间常数)。
通过将外部引脚设置为 1 为该电容器充电,通过 执行软件复位NVIC_SystemReset。重置后,它将运行引导加载程序。电阻连接到电容器将执行放电。固件更新后,您可以重置设备,它将运行到您的应用程序。
我们在一些应用程序中使用它,它运行良好。这种解决方案的缺点是需要外部电路,但实现起来非常容易,并且对所有STM32设备都是通用的。
在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快一点。