打印
[STM32F0]

STM32F091 从自举程序向应用程序跳转的 问题与解决

[复制链接]
1221|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
micoccd|  楼主 | 2021-11-15 09:42 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
前言前言
当使用 STM32 的 Bootloader 中的 GO 命令进行从 Bootloader 向用户代码进行跳转时,需要正确地在用户代码中设置向量表,
才能正常地运行用户代码。  

使用特权

评论回复
沙发
micoccd|  楼主 | 2021-11-15 09:42 | 只看该作者
问题问题
某客户在其产品的设计中,使用了 STM32F091RCT6,由于特殊的功能需求,将会使用到使用 Flash Loader Demonstrator
对芯片进行串口烧写后,直接跳入程序,但是客户发现烧写后根本就没有执行用户代码。

使用特权

评论回复
板凳
micoccd|  楼主 | 2021-11-15 09:43 | 只看该作者
调研调研
1.1.还原问题现象
我们使用 NUCLEO-F091RC 工具板来还原这个问题的现象。

再到 STM32Cube_FW_F0_V1.2.0 中找个例程来测试一下,为了方便观察,我们使用 Examples 中的 GPIO_IOToggle 来测试,
因为这是一个闪灯的程序。位置如下图所示:

使用特权

评论回复
地板
micoccd|  楼主 | 2021-11-15 09:44 | 只看该作者
使用 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 自带虚拟串口驱动,所以我们无需另接串口工具,就可以直接使用。在“我的电脑”点右键,进
入“属性”,选择“设备管理器”,可以看到:

也就是说,虚拟串口为 COM16。
所以我们打开 Flash Loader Demonstrator,做以下的配置:

使用特权

评论回复
5
micoccd|  楼主 | 2021-11-15 09:58 | 只看该作者
我们从 Nucleo 的用户手册 UM1724 中找到以下这张图:

在 Nucleo 上用跳线帽将 CN7 中的第 5 脚和第 7 脚短路, 拉高 BOOT0 脚,按一下 RESET 按键, 从 System Memory 启动。
我们回到 Flash Loader Demonstrator 的启动界面,点“ Next”进入下一个界面,再点“ Next ”再进入下一个界面,再点
“Next ”进入下一个界面,我们在这个页面中选择下载代码“ Download to device”,导入刚才编译生成的 STM32F091RCNucleo.hex,选中“ Jump to the user program ”,意思就是通过串口烧写完毕后,直接跳到用户代码去运行。如图:

点击“ Next”进行代码烧写。我们发现代码烧写完成后,按道理从 System Memory 中的 Bootloader 跳转到用户代码后,我
们应该看到 LD2 灯在闪烁。但是,我们发现,确实没有在闪烁!
将刚才放在 CN7 中的那个跳线帽拔掉,按下 RESET 键,可以看到 LD2 灯在正常闪烁,也就是说,程序正常下载进去了,看
起来像是没有跳转。

使用特权

评论回复
6
micoccd|  楼主 | 2021-11-15 09:59 | 只看该作者
2.2.问题分析
现在我们开始来分析这个问题。
我们打开 AN3155 这个应用笔记,这是关于 STM32 Bootloader 所使用的 USART 协议的描述。由于 STM32F091RCT6 中还
是有代码存在的,所以我们直接使用 GO 命令来测试一下跳转的情况。
再将 CN7 的第 5 脚和第 7 脚用跳线帽短接起来,按下 RESET 按键从 System Memory 的 Bootloader 启动。我们使用串口工
具来进行分析,将串口工具配置为:端口号 COM16,波特率 115200,奇偶校验设置为 EVEN,数据位为 8,停止位为 1。打
开连接
我们先发送“ 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 修改回用户代码的向量表。

使用特权

评论回复
7
micoccd|  楼主 | 2021-11-15 10:00 | 只看该作者
我们在参考手册 RM0091 的“System configuration controller (SYSCFG)”这一章中的 SYSCFG 配置寄存器 1
( SYSCFG_CFGR1)中看到 MEM_MODE[1:0]的描述:

于是, 我们将以下代码加入到例程中 main 函数最开始的地方。
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
SYSCFG->CFGR1 = (uint32_t)0x00000000;
重新编译, 生成新的 STM32F091RC-Nucleo.hex,我们再按之前测试时使用 Flash Loader Demonstrator 的步骤再测试一遍,
这次终于可以看到在串口烧写代码之后,可以正常进入用户代码并正常工作了——LD2 在闪烁。 用串口工具直接发 GO 命令,
也可以进入用户代码并正常工作了。

使用特权

评论回复
8
micoccd|  楼主 | 2021-11-15 10:01 | 只看该作者
结论结论
由于在用户代码中没有重新定位向量表,导致从 Bootloader 跳转到用户代码区后, 无法正常工作,产生 Hard fault 后系统复
位, 又回到了 Bootloader。

使用特权

评论回复
9
micoccd|  楼主 | 2021-11-15 10:02 | 只看该作者
处理处理
当需要使用 GO 命令从 Bootloader 直接跳转到用户代码时,必须注意在用户代码中要加入代码正确地设置向量表。

使用特权

评论回复
10
qcliu| | 2021-12-9 18:53 | 只看该作者
不需要关心地址是吗

使用特权

评论回复
11
tfqi| | 2021-12-9 18:55 | 只看该作者
如何自己修改向量表呢

使用特权

评论回复
12
wiba| | 2021-12-9 18:56 | 只看该作者
如何确保跳转的是正确的呢

使用特权

评论回复
13
zljiu| | 2021-12-9 18:59 | 只看该作者
跳入的这个代码怎么写啊

使用特权

评论回复
14
coshi| | 2021-12-9 19:02 | 只看该作者
轻易不使用go命令

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

104

主题

720

帖子

1

粉丝