打印
[信息]

【实战经验】STM32F091从自举程序向应用程序跳转的问题与...

[复制链接]
4409|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 香水城 于 2017-8-17 14:42 编辑

【实战经验】STM32F091从自举程序向应用程序跳转的问题与解决

前言
当使用STM32的Bootloader 中的GO 命令进行从Bootloader 向用户代码进行跳转时,需要正确地在用户代码中设置向量表,才能正常地运行用户代码。

问题
某客户在其产品的设计中,使用了STM32F091RCT6,由于特殊的功能需求,将会使用到使用Flash Loader Demonstrator对芯片进行串口烧写后,直接跳入程序,但是客户发现烧写后根本就没有执行用户代码。

调研
1.还原问题现象
我们使用NUCLEO-F091RC 工具板来还原这个问题的现象。

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

使用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,做以下的配置:

我们从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 灯在正常闪烁,也就是说,程序正常下载进去了,看起来像是没有跳转。

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 修改回用户代码的向量表。
我们在参考手册RM0091 的“System configuration controller (SYSCFG)”这一章中的SYSCFG 配置寄存器1
(SYSCFG_CFGR1)中看到MEM_MODE[1:0]的描述:

重新编译,生成新的STM32F091RC-Nucleo.hex,我们再按之前测试时使用Flash Loader Demonstrator 的步骤再测试一遍,这次终于可以看到在串口烧写代码之后,可以正常进入用户代码并正常工作了——LD2 在闪烁。用串口工具直接发GO 命令,也可以进入用户代码并正常工作了。

结论
由于在用户代码中没有重新定位向量表,导致从Bootloader 跳转到用户代码区后,无**常工作,产生Hard fault 后系统复位,又回到了Bootloader。

处理
当需要使用GO 命令从Bootloader 直接跳转到用户代码时,必须注意在用户代码中要加入代码正确地设置向量表。

对应的PDF:STM32F091从自举程序向应用程序跳转的问题与解决
更多实战经验请看:【ST MCU实战经验汇总贴】


沙发
643757107| | 2015-6-25 14:26 | 只看该作者
先发送“0x7F”给STM32,与Bootloader 确认USART 口,Bootloader 确认后,回送ACK(0x79),,,这么清楚的教程少见,沙了个发。

使用特权

评论回复
板凳
香水城|  楼主 | 2015-7-2 10:08 | 只看该作者
643757107 发表于 2015-6-25 14:26
先发送“0x7F”给STM32,与Bootloader 确认USART 口,Bootloader 确认后,回送ACK(0x79),,,这么清楚的 ...

Bootloader中这样的通信协议,在AN2606中有清楚的描述的。

www.stmcu.com.cn中可以下载英文V22版的AN2606,和中文V16版的AN2606

使用特权

评论回复
地板
643757107| | 2015-7-16 18:26 | 只看该作者
谢谢版主讲解,真是茅塞顿开。

使用特权

评论回复
5
狼烟客| | 2017-3-15 10:47 | 只看该作者
讲得好棒,谢谢城主分享

使用特权

评论回复
6
sanxingnote7| | 2017-3-15 11:43 | 只看该作者
版主的有BootLoader的教程吗?

使用特权

评论回复
7
sanxingnote7| | 2017-3-15 11:44 | 只看该作者
也没有想做过自举程序向应用程序跳转

使用特权

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

本版积分规则

认证:意法半导体(中国)投资有限公司
简介:STM32技术专家

596

主题

17099

帖子

287

粉丝