你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
STMCU小助手 发布时间:2022-2-18 20:41
前言( B# k) K: T' ^
当使用 STM32 的 Bootloader 中的 GO 命令进行从 Bootloader 向用户代码进行跳转时,需要正确地在用户代码中设置向量表,才能正常地运行用户代码。0 n7 T" n1 G, t* q& r+ L1 R! R
问题3 t! j% g! R+ m  X
某客户在其产品的设计中,使用了 STM32F091RCT6,由于特殊的功能需求,将会使用到使用 Flash Loader Demonstrator对芯片进行串口烧写后,直接跳入程序,但是客户发现烧写后根本就没有执行用户代码。6 S( |! ]! A6 e5 q

* ]8 }- ^& r/ d调研8 D4 S6 h5 ?3 s3 G# k4 t
1.还原问题现象
! }, r. D5 U, j& w/ z" A我们使用 NUCLEO-F091RC 工具板来还原这个问题的现象。- i; {7 J. F9 T$ P8 n/ S
) z0 D7 C0 f+ f: x! I. n
[OY{TI8AGDHFO5JQ_B4ZN1S.png ; K* `, E0 g! R+ c

; E5 F: b2 O' y. O9 @再到 STM32Cube_FW_F0_V1.2.0 中找个例程来测试一下,为了方便观察,我们使用 Examples 中的 GPIO_IOToggle 来测试,因为这是一个闪灯的程序。位置如下图所示:
7 }. C+ y! l$ k% p9 o& ?2 I
. B8 K+ _# }  g 2I747WO[SM{XWU$}D_ZJPTH.png ; l5 q' G# B- z. m

1 `* E+ d6 R! E9 m使用 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 软件将代码擦除掉。
2 x! j: O* B6 `) W7 c7 b5 o' M: m( b确认了 STM32F091RC-Nucleo.hex 没有问题之后,我们开始使用 Flash Loader Demonstrator 这个串口烧写软件进行测试。由于 Nucleo 板上的 ST-LINK 自带虚拟串口驱动,所以我们无需另接串口工具,就可以直接使用。在“我的电脑”点右键,进入“属性”,选择“设备管理器”,可以看到:/ I. H- v, y9 F) J/ k5 y% L
- y0 i0 {' l! ?+ ^2 n3 S
6ZTQ0X381N8`Q6CGZFF[V{D.png 2 M9 t5 J% Z. K, E

6 H. Z5 J5 V/ x4 J0 k6 h也就是说,虚拟串口为 COM16。3 N: j8 q, z& c: D
- s( d; {; F. P$ z
所以我们打开 Flash Loader Demonstrator,做以下的配置:
- w  {" m, D5 u3 r4 V5 w9 q
! _: z) _/ E! |; M0 V  a6 q3 y3 m 886)DKK$)O9C`3_`JSK1U3F.png
+ [  _+ l+ W( W1 ~( w( E
0 S0 C# v, U' \' J% Z" z我们从 Nucleo 的用户手册 UM1724 中找到以下这张图:
  l1 k/ t4 n& R! B5 v; \; U* t; c* d1 e1 b3 v) c; {5 ?
{$)K[%6%N[9NOX7WZ(WC2$A.png : }6 \) r+ X9 m& x: M3 ]6 `

4 `8 u( m- G0 W& O3 u在 Nucleo 上用跳线帽将 CN7 中的第 5 脚和第 7 脚短路,拉高 BOOT0 脚,按一下 RESET 按键,从 System Memory 启动0 M& l& ^; t5 [0 L  L

( p0 M- \% M/ S1 Y" d
: x: E+ [# G6 }$ o- _我们回到 Flash Loader Demonstrator 的启动界面,点“Next”进入下一个界面,再点“Next ”再进入下一个界面,再点“Next ”进入下一个界面,我们在这个页面中选择下载代码“Download to device”,导入刚才编译生成的 STM32F091RCNucleo.hex,选中“Jump to the user program ”,意思就是通过串口烧写完毕后,直接跳到用户代码去运行。如图:
- W1 V% }; Q6 _5 B* H; G5 b& d1 Z
/ x" E0 D) d- I6 o! `1 _3 o) j @$GJ@EW`9S$O6UM]TOJTQ.png ) ~; J; [8 b8 W1 K: F

8 H0 J# |3 b5 [- j# q. _点击“Next”进行代码烧写。我们发现代码烧写完成后,按道理从 System Memory 中的 Bootloader 跳转到用户代码后,我们应该看到 LD2 灯在闪烁。但是,我们发现,确实没有在闪烁!
  p- S( j  M! [! b" v! {% h! ?$ ?将刚才放在 CN7 中的那个跳线帽拔掉,按下 RESET 键,可以看到 LD2 灯在正常闪烁,也就是说,程序正常下载进去了,看起来像是没有跳转。' E. E1 ~7 m3 A/ o# ?0 Q: T

0 w3 y! e2 d. N0 J- u" O2.问题分析6 l  N9 |- k1 h' V, s( G# S
现在我们开始来分析这个问题。
; z; I2 t' @0 H, j6 @5 D1 E) g1 g% B5 g" o! f, H* h2 L
我们打开 AN3155 这个应用笔记,这是关于 STM32 Bootloader 所使用的 USART 协议的描述。由于 STM32F091RCT6 中还是有代码存在的,所以我们直接使用 GO 命令来测试一下跳转的情况。
! s+ i& m% C$ N) F# C! g5 R
) V" p  Z- f+ _7 {& \再将 CN7 的第 5 脚和第 7 脚用跳线帽短接起来,按下 RESET 按键从 System Memory 的 Bootloader 启动。我们使用串口工具来进行分析,将串口工具配置为:端口号 COM16,波特率 115200,奇偶校验设置为 EVEN,数据位为 8,停止位为 1。打开连接。( i4 [6 i" a& E6 _. ~
% ^% _( \4 }' L# m
我们先发送“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 修改回用户代码的向量表。! C* S- {) Q( i4 u* K
+ A0 P+ c' ]4 [$ d% n* o. g( J
我们在参考手册 RM0091 的“System configuration controller (SYSCFG)”这一章中的 SYSCFG 配置寄存器 1(SYSCFG_CFGR1)中看到 MEM_MODE[1:0]的描述:: V; d: L& @2 `

: X1 i! n4 o7 E7 J6 b. \
# K$ b) x+ A  M
3 W* `- n( P# O' U0 n于是,我们将以下代码加入到例程中 main 函数最开始的地方。
7 p7 A; |5 n. \+ K. p2 K  b
  1. RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
    * s9 g3 D* V: w! n& Z8 ^
  2. SYSCFG->CFGR1 = (uint32_t)0x00000000;
复制代码
; o. W8 Y/ i$ V
重新编译,生成新的 STM32F091RC-Nucleo.hex,我们再按之前测试时使用 Flash Loader Demonstrator 的步骤再测试一遍,这次终于可以看到在串口烧写代码之后,可以正常进入用户代码并正常工作了——LD2 在闪烁。用串口工具直接发 GO 命令,也可以进入用户代码并正常工作了。/ A1 D& H: z1 [! Q

! n9 F, g: c6 M* `结论
7 a- H7 u# J; n0 ^! T& E' u2 r由于在用户代码中没有重新定位向量表,导致从 Bootloader 跳转到用户代码区后,无法正常工作,产生 Hard fault 后系统复位,又回到了 Bootloader。# a5 B% r9 E4 m
4 B* o; [1 R8 U2 W  o# S3 J: T7 D% z
处理7 D0 r# j2 A, }) \& q+ |
当需要使用 GO 命令从 Bootloader 直接跳转到用户代码时,必须注意在用户代码中要加入代码正确地设置向量表。; z9 i; b" \- b8 y" u
7 e& I3 l6 \2 O8 S
赞 收藏 评论0 发布时间:2022-2-18 20:41

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版