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

STM APP更新过程中的问题

[复制链接]
yumeii 发布时间:2019-12-18 15:28
我们经常会基于STM32芯片来自行编写用户升级程序,通过该升级程序对片内应用程序代码进行更新升级。我们通常称该过程为IAP(In Application Programming),称该升级程序为用户bootloader或IAP程序,用来被更新或升级的代码程序为APP程序。
' Z3 ^" d. n6 r& Q
8 M: s5 i/ J9 j% n* Z9 U
6 {: [) K9 o$ r+ N9 Y3 W
1.png " `; m1 U( U5 H/ ~# U( W+ K
) v. }, [1 s# P, y: P3 n
; u1 E4 V' _4 t1 K+ y
一般来讲,IAP程序放在芯片启动后默认的起始地址空间。对STM32而言,多是在片内0x8000000起始的Flash地址空间,而用户APP程序地址空间由用户自行指定。
5 X6 E& |. T7 p* s6 j& Z0 b
$ E1 f6 c, J3 ]! P$ \

3 b# v# }. a" D( |下面基于结合一个小实例来聊聊在做STM32 IAP应用中可能遇到的几类常见问题。: X; X& q! g, e, I9 {" `

/ H% N0 R. K# }' }# }- I' L
( y) u+ q( i% p
这里使用STM32F302_Nucleo板,模拟设计了一套IAP和一套APP代码,在IAP中使用了TIM2,在其更新中断里使用UART1打印输出目前所在工作区,完成三次打印输出动作后跳转到APP去执行程序。我在APP程序里使用了TIM1,同样在其更新中断里使用UART1打印输出当前所在工作区,也是三次动作后跳转回IAP程序区。【开发环境为MDK,基于stm32Cbue库组织代码】, V" r, |7 L+ V: E
/ W2 |! b+ n2 z' P. [- ^0 D7 ]5 w
3 p6 M, z6 ^9 ^! o
基于ARM MDK环境的IAP相关配置如下:
: w' H& s' R9 a% O6 J7 K
. S" ~+ A9 o$ U0 a& a- H+ R. {

) W/ [& I, J- m! b- B) w* S. m  l9 L 2.png : Y3 p- o) X3 r3 x2 U, a& X
. h9 c8 Z1 W2 w( J7 ?- V

6 P# J3 G$ {3 g; p3 m基于ARM MDK环境的APP相关配置如下图所示:; W9 l$ i* m+ c. b4 a$ h' ^9 e2 e* D. ]

1 X# e5 }& i# f
  R- v9 A1 u& q' d5 E/ p
3.png
% K- I1 K$ d1 K3 o, ^' J- v# j5 Y9 ?7 ?$ I0 A0 R9 w

* ?9 h" L2 S3 M  U* u# a; {根据上述配置,IAP放在片内0x8000000开始的0x3000大小的flash空间内,APP放在0x8003000开始的剩余空间内。最后的结果应该是下面这样子,程序在两个区间来回跳转,输出结果可控有规律,符合设计预期。【下面为Printf输出截图】: b+ [" v9 E& v$ Z( {7 y
7 M5 n" h  V3 d& c$ F7 Q
4 O; T) m  L' R0 @( `# g: p
4.png 2 B1 ?2 ?: E5 ]7 p" `$ A+ l0 _
: Z* D% D( {" i

2 ]& l( s  ]7 C  z! e& h现在具体看看我们在做IAP应用中可能遇到的几类问题。

3 P( W3 y% g/ y' u& m第一类的问题,就是指定APP程序空间的起始地址时出错。

. r& r0 Z# x& C6 o8 u% K
  w! j0 Q9 Q& e+ D0 j虽然说,对于用户APP程序空间,用户可以自行安排,但我们在安排APP程序空间的起始地址时要注意两点。第一点,我们要给IAP程序代码留足空间,APP程序空间一般在IAP代码物理空间的后面,不能出现交叉重叠的情况。另外一点,安排APP的起始地址的时候,不能将地址放在跟IAP代码位于同一页或同一扇区的地方。否则在通过IAP做代码升级时,对APP区域擦除时就会连同IAP代码自身也一起擦掉。这些信息需要查看STM32各个系列参考手册中memory章节。【下面两幅截图分别来自STM32F30X系列和STM32F40x/41x系列的参考手册】
/ z  f  J% V) h1 ~" `

% j. F! B- Z, i0 W" W7 ?, i9 G

' J& l9 W* r( r: \6 s( _ 5.png
# Q$ h$ ?  a) k9 N3 e5 V/ @  _) U5 i
) R* y8 p8 U( o1 _( l+ {
6.png 0 O- i! A8 E  a. H7 N

8 I8 b; Y* x* N

5 o, E+ @3 c; ?4 \% [第二类问题,就是中断矢量表的地址给错或相关代码放错了地方。
1 {  g' L" j5 _6 V$ U

7 O9 A7 r( x2 v% lSTM32芯片里往往都有个中断矢量表,该表的起始地址除了STM32F0系列芯片外,都可以通过配置SCB_VTOR寄存器来指定。我们在给各个STM32工程配置中断矢量表地址时,要跟该工程所在地址空间的起始地址一致。具体到这里,IAP工程的中断矢量表的位置在0x8000000,APP工程的中断矢量表的位置就在0x8003000.
0 J8 d* V  \# o3 z$ j' Z
' {- g2 x% X/ L  K0 {; B. C8 U1 j+ o

' u/ {( t* b0 G$ Y% i: N* j) ` 7.png 3 H3 ^! K3 A6 b$ e' h  s7 ?6 M

# y( J9 _1 f# K/ J% h2 T

+ s& ]: q& p1 z; ^9 L  Z( r另外,在IAP应用中,关于中断矢量表地址的赋值代码还往往因为摆放位置不当而导致问题。对这个矢量表寄存器VTOR的赋值最好放在启动文件里的复位程序入口的系统初始化函数里,即.s文件里调用的SystemInit()函数。这样保证运行用户程序前已将正确的中断矢量表地址准备好了。
( m# g5 ?0 W2 Z- z/ |2 f! s& g7 y/ b/ M/ m1 T
. |6 [4 C/ v3 z: S4 l7 \8 B9 q0 Y
8.png
( c6 r$ g8 @2 M3 V$ {$ }% x
% ]) P1 {& Q- r! A! d+ ?
6 _! F/ k  c2 f& u6 b
结果有些人将对VTOR寄存器的地址赋值操作不是在启动文件里完成,而是放到了用户main()函数里去执行。如果这样,若在该赋值语句执行之前没有任何中断发生倒也不会有什么问题。如果说在该赋值操作之前发生了中断,由于正确的中断矢量表地址又没准备好,这时硬件会到默认的而又不是我们预期的地方去提取中断向量地址并运行程序,此时不出问题才怪。" h  I+ E' N. O% p! ]
/ D3 @, l! G( Y  i* g1 [
% Z# h" p! F+ D' o( Q
第三类问题,就是跳转过程中跟中断有关的处理不当导致异常。较为常见的情形就是在跳转前没有将当前工作区开启过的中断做关闭禁用处理。

+ ?* Q  m$ o1 \" u
3 d6 }; X  L5 Z3 |) v0 H我们结合上面的实例来看看。在IAP区我开启了TIM2的中断,如果在在跳转到APP之前不对当前区域的TIM2的中断相关配置做清除整理,看看会出现什么结果。将下面方框中有关TIM2外设及中断相关的代码屏蔽掉,即对开启过的TIM2中断配置不予理睬,就直接跳转到APP区。【此时APP代码不动】

2 a# q( z- [/ g9 Q8 p8 D2 }% y+ A
1 r9 Z- H: ~3 d

" {, _  D  v. r/ Q 9.png
, r. _4 Y: G% c6 m  o. t; e8 k6 l2 {, X2 X: _

1 `* [. f7 Y+ m9 f' Q这样编译运行后,发现输出结果跟我们预期的不一样了,输出结果明显有点乱了。实际的产品应用肯定不能接受类似这种程序不受控的状况。* b7 `6 p9 e& Y7 {

& O" A- W6 ]; z! r" E

- _2 P. j5 p/ l 10.png
8 T7 s& H7 Z7 |9 w+ _
3 y$ z3 Q8 X3 ^! Z

& F  [6 A" g) _. p# G还有一种跳转处理不当的情形,那就是让跳转动作发生在中断服务程序里。
0 ~' s; k! Y& j, |, a还是结合上面实例来看,将从IAP跳转到APP的跳转执行代码放在TIM2的中断里完成,看看结果会怎么样?【此时APP代码不动】% E# z9 i5 W/ O
, Y/ `; ~  b( W  w% z
2 G8 K% p9 `1 }1 D4 Q
11.png & K/ B9 R8 c3 l) b

/ S/ \) y1 F6 T, q( v  c: D6 {& f
5 c" E; Q6 j7 y* B) g4 g
当将跳转代码放到TIM2的中断服务程序里后,编译运行,结果发现这一跳就死机了。输出就变成下面的样子不动了。虽然执行了跳转动作,但APP程序没能得到正确运行,即跳转失败。所以,我们不要将跳转操作的代码放在中断里执行。! m' ~% w8 Q: ~$ ]! f4 o0 _9 G* ^
0 m1 ^1 u2 w2 U

& |6 e$ K# m" w  a/ a8 [5 x 12.png 8 x: l/ i& L% L4 Y& ]

2 S9 j0 ~; q# a  A! o  Q
, {# j- y: x3 N4 f8 t) D, [
第四类的问题,也是这里要聊的最后一类问题。
: k) w' Z) t* b2 [/ X

9 H  t) n; o, Z, a% q  u2 @7 e我们做IAP应用自然要涉及到Flash编程,不同的STM32系列所支持的编程模式上可能有差异,有的仅支持半字编程模式,比方STM32F1系列,有的只支持双字编程模式,比方STM32G4系列,有的可能支持多种编程模式,比方STM32F4系列可以支持从字节到双字的编程模式。关于这点,我们在不同STM32系列间做移植时要特别注意。另外,虽然说有的系列,比方STM32F4系列支持多种种编程模式,但选择不同的编程模式时,芯片的供电一定要与所选择的编程模式相匹配,不然可能出现编程不可靠情况,这点常被人忽视,当出现问题时往往很难想到这里。当因为Flash编程导致的异常现象往往也很诡异,不太容易查找原因。【下图是STM32F4芯片有关编程模式与供电要求的表格】
3 B) d4 y) ?  @
+ j4 X, O* E- X  s! M1 z
2 u8 f' f3 b$ M( q2 A1 D2 U
13.png 7 H7 o& y: f: O5 t. a5 I. E

. v) f% N% E7 w1 g
/ Z- b3 R/ F: h. i. m0 I
好,上面重点分享了基于stm32IAP应用中比较常见的几类问题及注意事项。其实,产品开发过程中因为没有注意上面提到的几类问题,实际的异常现象往往跟具体应用有关,可能五花八门。
7 U: [2 N" I4 n/ b
' f4 _% J  C* ^2 c! Z* H# |" j
赞 收藏 评论1 发布时间:2019-12-18 15:28

举报

1个回答
jeffhe1 回答时间:2019-12-19 09:19:08
非常詳細, 感謝大大 , 學習了 , 果然 bootloader 不是那麼好玩
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版