STMCU小助手
发布时间:2022-2-18 20:41
|
前言: w3 q9 T1 W# r6 _. R+ W/ j 当使用 STM32 的 Bootloader 中的 GO 命令进行从 Bootloader 向用户代码进行跳转时,需要正确地在用户代码中设置向量表,才能正常地运行用户代码。" [1 y& n' h. z& W# ]" e% W1 j 问题 某客户在其产品的设计中,使用了 STM32F091RCT6,由于特殊的功能需求,将会使用到使用 Flash Loader Demonstrator对芯片进行串口烧写后,直接跳入程序,但是客户发现烧写后根本就没有执行用户代码。 / {/ o& q7 d8 I7 D X% Q0 Y' N 调研 1.还原问题现象 ) m, Q2 i8 ^- s. F 我们使用 NUCLEO-F091RC 工具板来还原这个问题的现象。+ M" G% j+ P. c4 J7 V8 D! V
" ?& H" t) {# c 再到 STM32Cube_FW_F0_V1.2.0 中找个例程来测试一下,为了方便观察,我们使用 Examples 中的 GPIO_IOToggle 来测试,因为这是一个闪灯的程序。位置如下图所示:' n. S. r6 h4 M' P! Y( n a
使用 IAR 将项目打开,进行编译,生成 STM32F091RC-Nucleo.hex 文件,可在\Examples\GPIO\GPIO_IOToggle\EWARM\STM32F091RC-Nucleo\Exe 文件夹中找到。使用 USB 线连接 NUCLEO-F091RC,使用 STM32 ST-LINK Utility 软件将 STM32F091RC-Nucleo.hex 代码下载到 NUCLEO-F091RC,观察 LD2 灯,可见其闪烁。我们再用 STM32 ST-LINK Utility 软件将代码擦除掉。 确认了 STM32F091RC-Nucleo.hex 没有问题之后,我们开始使用 Flash Loader Demonstrator 这个串口烧写软件进行测试。由于 Nucleo 板上的 ST-LINK 自带虚拟串口驱动,所以我们无需另接串口工具,就可以直接使用。在“我的电脑”点右键,进入“属性”,选择“设备管理器”,可以看到:, s: k+ B% N+ \8 q" W* j: k4 y , v/ O+ Z/ y: U/ l' F
也就是说,虚拟串口为 COM16。: N5 N% z4 |# }* l 0 E: I- M1 J7 A! P 所以我们打开 Flash Loader Demonstrator,做以下的配置:* n# `# ? d$ n) x
/ h( |9 h. v! f0 C1 R+ Q 我们从 Nucleo 的用户手册 UM1724 中找到以下这张图:
C$ ?6 ]8 T. } 在 Nucleo 上用跳线帽将 CN7 中的第 5 脚和第 7 脚短路,拉高 BOOT0 脚,按一下 RESET 按键,从 System Memory 启动 ; N; U+ `8 j# d, y5 h$ V 我们回到 Flash Loader Demonstrator 的启动界面,点“Next”进入下一个界面,再点“Next ”再进入下一个界面,再点“Next ”进入下一个界面,我们在这个页面中选择下载代码“Download to device”,导入刚才编译生成的 STM32F091RCNucleo.hex,选中“Jump to the user program ”,意思就是通过串口烧写完毕后,直接跳到用户代码去运行。如图:
点击“Next”进行代码烧写。我们发现代码烧写完成后,按道理从 System Memory 中的 Bootloader 跳转到用户代码后,我们应该看到 LD2 灯在闪烁。但是,我们发现,确实没有在闪烁! 将刚才放在 CN7 中的那个跳线帽拔掉,按下 RESET 键,可以看到 LD2 灯在正常闪烁,也就是说,程序正常下载进去了,看起来像是没有跳转。 2.问题分析 现在我们开始来分析这个问题。, I9 ]: I! m- o- m) ?" B 我们打开 AN3155 这个应用笔记,这是关于 STM32 Bootloader 所使用的 USART 协议的描述。由于 STM32F091RCT6 中还是有代码存在的,所以我们直接使用 GO 命令来测试一下跳转的情况。4 R4 W4 O7 ?# y: e 再将 CN7 的第 5 脚和第 7 脚用跳线帽短接起来,按下 RESET 按键从 System Memory 的 Bootloader 启动。我们使用串口工具来进行分析,将串口工具配置为:端口号 COM16,波特率 115200,奇偶校验设置为 EVEN,数据位为 8,停止位为 1。打开连接。. _" B: v. L* M* Q, \ $ l8 F) {: L, X* C7 d 我们先发送“0x7F”给 STM32,与 Bootloader 确认 USART 口,Bootloader 确认后,回送 ACK(0x79),我们可以看到正常收到0x79,所以通讯建立。现在开始测试 GO 命令。按照 GO 命令的流程,我们发送“0x21 0xDE”启动 GO 命令,Bootloader 正常回应 ACK(0x79)。现在要测试跳转到用户代码那边运行用户代码,所以我们发送 Main Flash memory 的地址 0x0800 0000 和 Checksum(XOR(0x08, 0x00, 0x00,0x00)=0x08),也就是发送“0x08 0x00 0x00 0x00 0x08”,这个时候,Bootloader 也正常地回应了 ACK(0x79)。那么看起来,程序是正常跳转了,可是为什么就是看不到运行用户代码而能看到的 LD2 闪烁呢。看起来,很有可能会是从 Bootloader 跳转到用户代码后,在用户代码执行过程中出错了,导致复位,并回到了 Bootloader 程序。那么,从 Bootloader 跳转到用户代码之后执行出错的最可能原因就是向量表设置不对。我们从AN3155 中看到这么一句话:“The Jump to the application works only if the user application sets the vector table correctly to point to the application address.”也就是说,我们必须在用户代码中设置正确的向量表。所以我们回到 GPIO_IOToggle 的例程,加入代码将向量表从 Bootloader 修改回用户代码的向量表。 我们在参考手册 RM0091 的“System configuration controller (SYSCFG)”这一章中的 SYSCFG 配置寄存器 1(SYSCFG_CFGR1)中看到 MEM_MODE[1:0]的描述:. n; s( n# n, _ " u& u/ y: Y6 N' ~
于是,我们将以下代码加入到例程中 main 函数最开始的地方。 A; r9 o& c; K+ V
重新编译,生成新的 STM32F091RC-Nucleo.hex,我们再按之前测试时使用 Flash Loader Demonstrator 的步骤再测试一遍,这次终于可以看到在串口烧写代码之后,可以正常进入用户代码并正常工作了——LD2 在闪烁。用串口工具直接发 GO 命令,也可以进入用户代码并正常工作了。6 y7 K! O: ^. U 结论) K& o+ Y) | w2 c. R 由于在用户代码中没有重新定位向量表,导致从 Bootloader 跳转到用户代码区后,无法正常工作,产生 Hard fault 后系统复位,又回到了 Bootloader。3 ?& C7 C8 t( L! I4 f+ v; }9 j 处理 当需要使用 GO 命令从 Bootloader 直接跳转到用户代码时,必须注意在用户代码中要加入代码正确地设置向量表。 |
DMA 原理从 0 到 1:为什么它能解放 CPU?一文讲透 DMA 的工作流程
小白也能明白的STM32的低功耗与唤醒机制
STM32系统中2种数据掉电保护的方法
分享STM32F051中文参考手册(重制书签版)
AI工具训练营-用ChatGPT解决HID Keyboard实现的问题
STM32固件库分享,超全系列整理
STM32小白入门指南:从基础到OTA实现方案
STM32超详细学习笔记
新手必看!STM32单片机应该怎么学?
如果你解决了这些问题,就可以直接学STM32
微信公众号
手机版