STM32F091 有一项特殊的功能,就是在空片的情况下既可以使用 ST-Link 等编程工具进行编程,也可以使用 System Memory 中的 Bootloader 进行下载代码。这完善了整个编程体系,给用户在编程方案的选择上带来很大的方便。但是,在某些特定应用上,好心也可能会干坏事哦。 下面就来聊聊这个事是怎么来的,并且找出相应的对策。 问题 某客户在其产品的设计中,使用了 STM32F091RCT6。客户使用 ST-Link 对 STM32F091RCT6 进行编程,发现对空片进行编程之后,必须要重新上电才能运行用户代码;但是如果不是空片,则编程后就可以直接运行用户代码。由于客户的测试系统是直接烧写完芯片后在不断电的情况直接进入测试模式,如果空片烧写需要断电的话,带来一定的麻烦。客户希望搞明白这件事,并希望找到办法,能在空片编程后也可以直接运行用户代码。 调研 1.还原问题 在这里,使用带有 STM32F091RCT6 的 NUCLEO-F091RC 板来进行问题还原,将此 Nucleo 板通过 USB 线连接到电脑。打开 STM32 ST-LINK Utility,点击“Connect to the target”按钮进行芯片连接,连接后打开一个准备好的 LED 灯闪烁的.hex 文件代码,点击“Program verify”按钮准备进行编程。
在这里,我们勾选了“Reset after programming”,目的在于编程后对芯片进行复位,可以运行用户代码。然后点击“Start”按钮开始进行编程。 编程之后,按道理可以看到 LED 灯闪烁的,但是并没有出现。需要给 MCU 进行断电后,重新上电才能看到 LED 灯闪烁。也就是说需要一次上电复位才能运行用户代码。 2.分析问题 先来回顾一下 STM32F091 的参考手册 RM0091 对于 Empty Check 的描述:
首先,芯片内部存在一个查空标志,用来标志芯片是否为空片。这个标志位在 BOOT0 脚被定义到从 Main Flash memory 启动的时候使用。当这个标志位被置“1”的时候,此芯片被认为是空的,系统将从 System memory 中启动 Bootloader,以允许用户进行代码下载,即使现在 BOOT0 脚定义的是从 Main Flash memory 启动。此标志位只在载入 Option bytes 时更新: 当地址 0x0800 0000 读出的内容为 0xFFFF FFFF 时,此标志位置“1”,否则为“0”。这意味着当烧写完一个空片后需要在系统复位后执行用户代码的话,是必须要重新上电以产生或者在 FLASH_CR 寄存器中置位 OBL_LAUNCH 来启动 Option byte loader reset,以清除此查空标志。 现在就可以来分析目前所遇到的情况了: 当空片通过 SWD 连接到 ST-Link 进行烧写的情况下,由于上电时空片检测检测到此芯片为空片,查空标志被置位,所以系统此时从 System memory 中启动 Bootloader 开始运行。通过简单的 SWD 接口对芯片进行编程,勾选的“Reset after programming”将在编程结束后在 RESET 引脚上产生一个复位信号,但是不幸的是这个复位并不能清除查空标志,导致复位后仍然从 System memory 中启动 Bootloader,而没有运行用户代码,也就是我们之前遇到的现象。 一般情况下,我们都可以通过重新上电来产生 POR 以清除查空标志,从 Main Flash memory 启动运行用户代码。但是,客户目前的这种特殊需求就会带来一定的麻烦。还有一种应用也会比较麻烦,也就是使用锂电池的产品,而且这个电池直接焊接到用户板上,无法方便地进行断电上电。此时,若是空片是焊接在板子上进行在线编程,那么,问题来了。空片编程之后,由于不方便进行断电,而无法完成 POR 的动作,不能运行用户代码也就无法实现一个 Option byte loader reset。查空标志无法清除,程序运行将锁死在 System memory 的 Bootloader。
|