在上一篇文章中,我们讨论了STM32 ARM芯片的SWD接口的使用方法。不过,该接口并不是与这款设备交互的唯一途径:其引导加载器还提供了一个串行接口,尽管在功能上没有SWD接口强大,但是仍然可以用来读写闪存。
当然,这种用法好像不太自然:首先,因为该设备很小,周围又有引脚,因此,访问SWD接口不太可能比访问串行接口更难。此外,SWD和串行引导加载器都可以通过RDP(读保护)进行“锁定”。然而,我们已经看到,许多芯片中不同的调试/编程接口都具有不同的安全级别。同样,串行端口通常比JTAG/SWD更显眼或更易于访问。实际上,本文的主要目的,是为读者介绍如何关阅读数据手册和原理图,如何将器件切换到另一种引导模式,以及如何选用不同的工具。
什么是引导加载器?
引导加载器通常是在处理器上运行的第一段代码。它的任务是初始化硬件并执行固件代码。在复杂系统上,通常会有一个“主”ROM引导加载器永久存储在设备中,以调用“辅助”引导加载器。
在非常简单的ARM微控制器(如我们使用的Cortex-M0)上,则不需要把事情搞得这么复杂:处理器会查找“向量表”中的第二个条目(复位向量),并执行该地址处的代码。
然而,STM32提供了一个ROM引导加载器,它被存储在一个叫做“系统内存”的东西中(意法半导体就是这么命名的,至于为什么这么命名咱也不敢问)。此外,我们还可以通过引脚和闪存选项,来选择不同的引导模式:
· 从闪存运行(正常操作)
· 从系统内存运行(我们考察的就是这种模式)
· 从SRAM运行(有时用于编程)
此外,STM32F030R8上的系统内存允许使用串行接口与设备进行通信,而其他一些STM32则支持通过I2C或USB接口与设备进行通信。
随处可见的数据手册
对于STM32系列来说,我们需要关注的文档有4套:
· 产品规格说明书(通常只是“数据手册”)——这主要涉及物理和电气接口。引脚布局也可以从这套文档中找到;对于STM32来说,内存映射也包括在该文档中。
· 参考手册——包含外围设备和设备内部寄存器的详细说明。
· 程序员手册——包含了处理器指令集的详细信息。
· 应用说明——有关设备特定功能实现的小型文档。
对于STM32系列来说,其大部分或全部文档都是公开的。
在整个半导体行业中,各种文件中使用的术语和包含的信息通常是完全不一致的。
引导模式
在产品规格说明书中,我们可以看到“引导模式”一说,但是并没有提供太多的信息。
在参考手册中,详细介绍了进入各种启动模式的方法。假如我们要进入的引导模式为“系统内存”模式,则需要为这个函数提供两个输入:nBOOT1位和BOOT0引脚。
默认情况下,设备是从闪存启动的。因此,BOOT0引脚必须接上下拉电阻。
nBOOT1位为“x”,表示“无需关心”。我们需要搞清楚它到底是什么,以及是否需要改变它。通过在参考手册中搜索nBOOT1,我们发现它是选项字节中的一个二进制位。
这里的默认值是0x00FF55AA——我们需要确定第20位的值是多少。如果您熟悉十六进制的话,那么这个问题的答案就很明显了;否则的话,可以使用计算器将其转换为二进制形式。
为此,我们可以在Windows计算器中输入上面的十六进制值,并将其转换为二进制数值。
现在,我们就可以直接数出相应的位数了,不过,这样比较费劲;相反,如果点击相应的点状按钮,窗口将给出一些提示,这样数起来就方便多了:
默认情况下,第20位(nBOOT1位)被设置为1。这就是我们要找的结果!
(对于十六进制数值0x00FF55AA,第20位的值明显为1,因为它所在的字节为0xFF,也就是所有位皆为1)
现在,我们需要搞清楚如何设置引脚BOOT 0。
为此,我们需要回顾一下产品规格说明书。
这是一个具有明确标记的引脚——60引脚。注意,永远不要假设数据手册中的图像会提供可搜索的文本!相反,我们有时必须一页一页地肉眼搜索。
虽然我们可以用万用表找到该引脚的去向,但别忘了这是一个开发板:我们是有原理图可供资助的。
关于原理图,有几点值得注意。
两个黄色的框(U5A和U5B)均表示微控制器U5。它只是分成不同的部分,以使文档更易于理解。
针脚编号不是按顺序组织的。同样,它们是按照使文档更易于理解的顺序进行组织的。
黄色菱形框表示一个信号(或一组信号)要跳到另一页。
在U5B上可以看到引脚BOOT0(60引脚),它引向R33——一个10K电阻。这是一个“下拉”电阻,被设计用于保持逻辑电平为0,除非该引脚直接连接到高电平。
那么,BOOT0信号传到哪里去了呢?它跳转到了另一页。
准确来说,是传到了连接器CN7的7号引脚——很好! 我们需要做的就是将其连接到高逻辑电平,这样的话,该设备就会进入系统内存引导模式。方便的是,紧挨着7号引脚的5号引脚就是“VDD”,即处理器的供电电压。我们可以使用CN11或CN12中的一个备用跳线(它们只是备用跳线的支架)来桥接两者。
这很容易测试:您的电路板应该运行令LED闪烁的代码。之后,请将跳线接上,然后,按黑色的复位按钮,这时LED应该停止闪烁,因为相关代码不再运行了。
寻找UART
产品规格说明书中提到,可以通过引脚PA14/PA15或PA9/PA10来访问引导加载器。不过,我们想要的是最容易的访问方式。
让我们再次回到原理图上,我们发现:引脚PA14/15是通过CN7上的引脚15和17引出的,并且它们是彼此相邻的。
与引导加载器进行交互
我们知道,设备是通过引导加载器进行启动的,同时,我们还知道要连接到哪些引脚。虽然该开发板提供了内置的USB串行适配器,但它是通过PA2/PA3连接到USART2的。不过,由于重新配置电路板并非易事,因此,我们将使用外部USB串行适配器。
如果您不熟悉串口的使用方法,请回顾一下介绍与串口进行交互的那篇文章。有一点请牢记,TX转RX,RX转TX。
我们将要使用的软件叫做stm32flash。该软件可以从SourceForge网站下载的——是的,SourceForge网站仍然还在。我们建议大家下载名为“stm32flash-0.5.tar.gz”的最新版本。
下载到本地后,大家可以通过下面的命令来完成解压、构建和安装过程:
tar -zxvf stm32flash-0.5.tar.gz cd stm32flash make sudo make install
在给STM32开发板上电后,利用跳线拉高BOOT0的电压,并连接我们的串行适配器,然后,运行下列命令:
sudo stm32flash /dev/ttyUSB0
上面的命令将查询设备以获取相关的信息。如果该命令无法运行的话,尝试翻转TX和RX。
现在,借助于相关命令,我们就可以读写闪存了。
小结
实际上,我们曾经在LPC5460x系列芯片上用过非常类似的技巧,来禁用SWD/JTAG;同时,您还可以将设备设置为USB引导模式,以便通过USB读取固件。当我们遇到问题时,一定要多翻翻相应处理器的数据手册,说不定就能找到类似这里介绍的“隐藏”功能。
本文翻译自:https://cybergibbons.com/hardware-hacking/reading-and-writing-firmware-on-an-stm32-using-the-serial-bootloader/如若转载,请注明原文地址: