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

【经验分享】STM32F0 不同代码区跳转时总失败…这些操作你做对了吗?

[复制链接]
STMCU小助手 发布时间:2022-2-26 16:47
对于 STM32 用户,经常会涉及到通过用户启动程序实现对用户应用程序的更新升级。一般来讲,用户启动程序主要用来跟外界通信,获取新的用户程序代码并实现对用户代码区的应用程序升级。用户应用程序是指实现各种用户功能的代码。& `7 e! A& q- d3 v& b$ j+ l
在这个过程中,往往需要做从用户引导程序区(以下简称【BOOT 区】)到用户应用程序区(以下简称【APP 区】)的跳转,有时可能还需实现从用户应用程序区跳回到用户启动程序区,甚至不同用户程序区的互相跳转等操作。在这些跳转过程中,常常有人的开发工作在此遇到阻碍,甚至破费周折。
! ~# R6 `8 e7 {1 h3 p
4 _/ e/ n" o$ N  n  @9 ]; zSTM32F0 代码区跳转6 ~3 v8 f" ]6 h: v5 ]" R  P! I8 w8 u
在此我们以 STM32F0 为例,就芯片内不同程序区的跳转问题做些交流与介绍,限于篇幅,这里仅直接介绍具体操作和注意事项,不做过多拓展介绍。相关知识点可阅读 STM32 芯片参考手册、STM32 相关内核编程手册。
% w) C5 v. e# P2 [9 b" l2 f4 i: o& K# _$ Z0 |: l0 z
下面介绍中提及的集成编译环境是指 ARM MDK,硬件基于 STM32F072RB Nucleo 开发板。后面我将逐一介绍不同跳转操作的基本流程和注意事项,涉及以下三种情况:& E, ~3 ~! Q& i9 \( Z5 `
 从【BOOT 区】跳转到【APP 区】
4 k( [) _9 }$ Z* A- ]+ z1 U: O 从【APP 区】跳转到另外新【APP 区】5 n# P, C/ k, L3 h3 h+ P+ g+ k
 从【APP 区】跳回【BOOT 区】
3 q: Q6 M9 ?% `1 n) _4 A8 w2 Y一般来讲,不同区段的执行代码我们通过建立不同的工程项目来实现,最终将不同区段执行代码写入芯片。这里假定 BOOT 区对应的内部 FLASH 地址段为 0x8000000—0x8004000,APP1 区对应的内部 FLASH 地址段为 0x8004000—0x8008000, APP2 区对应的内部 FLASH 地址段为 0x8008000—0x800C000.! U  t" J5 V1 n& t6 o. r! c7 c' W4 i

2 u' [9 X: c! z1 H) ?4 X* e5 i 0GN(9UI)P~PEX[EH{(0QA(3.png
3 t* U. Y& @/ L1 D% T  \7 ]% p& C2 G0 \
从【BOOT 区】跳转到【APP 区】
& j4 d. O+ v; q5 h7 G# O2 F: q' h9 G) Y% z- y" l" n3 P
先说从 BOOT 区跳转到 APP 区。这个跳转代码比较简洁、简单,注意跳转前要关闭刚才程序区开启过的所有中断使能,保证所有中断请求位都被清除,不是简单的关闭总中断,否则往往隐患多多。BOOT 区相关跳转代码如下:6 P1 o8 c: Q. i' m2 S% {0 `  n& D
  1. If ( Jump_Condition Satisfied )
    ' R6 H5 b$ R" o/ ~
  2. { if(((*(__IO uint32_t*)APPLICATION_ADDRESS_APP) & 0x2FFE0000) == 0x20000000)
    * L$ ]+ {, B! M& _1 G1 p7 U
  3. { /* Jump to user app */
    - Q9 c2 \1 x; ~" G8 Q  k5 d5 _
  4. JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS_APP + 4$ x- ]) G0 |9 {& u& B: V' P
  5. JumpToApplication = (pFunction) JumpAddress;
    ) Y4 v, Z0 k; v$ V
  6. __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS_APP);: x$ ~9 O, m" z) E+ x$ p8 R* z
  7. JumpToApplication();8 C( N( o9 y1 ^! v' [: ]
  8. }
复制代码
: J+ B; E' ?4 g1 w& N
这个从 BOOT 区到 APP 区的跳转最终能否成功,关键还是取决于 APP 区代码相关配置及准备工作。假设这里的 APP 区是上面提到的 APP1 区,内部 FLASH 地址段为 0x8004000—0x8008000,那么在 MDK 的 option 项里的 memory 配置板块要做正确配置,即 flash 空间与 ram 空间的配置,如下图所示:
+ O5 `2 D; q! ?- a. Z0 Y( d/ h" Z- k7 j
S16[CYC[)F5H{){R8PQ376H.png . x0 `) T6 }; ~: o. d* H

9 s/ m/ Y: W% U+ E* HIROM1 的配置就是 APP1 代码摆放的起始空间地址及长度。IRAM 的配置要注意先保留 48个字的空间用来存放中断矢量表的内容。因为 stm32F0 芯片的中断矢量表的大小就是 48个字(即 0xc0 字节)。至于剩下的内部 RAM 空间大小由芯片本身的 RAM 容量决定(这里是基于 STM32F072RB 芯片,其内部 RAM 总容量为 0x40000)。
/ M) ?" m3 S. f! x' ^3 N0 U2 h' G2 {# c
另外一件很重要的事情就是做中断矢量表的拷贝。在 APP1 区的 main()程序开头部分,将放在 flash 程序空间起始部分的连续 48 个中断矢量地址表拷贝到内部 RAM 的起始地址段。即将矢量表从 0x8004000 地址开始拷到 0x20000000 开始的连续 48 个字空间(前面提到的存储配置正是为了配合这个拷贝操作)。基于 MDK 环境的参考代码如下:  L6 m. L) w3 @0 m. G" d* g

4 Y) p+ Y, W' A% T
: u; N4 `8 e7 y6 {' m& G
  1. #define APPLICATION_ADDRESS4 (uint32_t)0x08004000
    3 f1 L9 T  \' U9 O; k! L$ L1 I; R
  2. __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));7 ~* c: Q* d5 T: ^5 U5 _
  3. int main(void)
    ! W& Q9 ~. T- F6 G/ i, G6 l
  4. { HAL_Init();5 Z5 T% i% b, Z  ?/ r$ w' _: j+ P
  5. SystemClock_Config();+ O, ^# G5 ?% ?( W: N0 |
  6. for(i = 0; i < 48; i++)
    ( O$ ]( w$ s% s# A6 G
  7. { VectorTable[i] = *(__IO uint32_t*)(APPLICATION_ADDRESS4 + (i<<2)); }/ h% ^. {1 a6 b. A
  8. /* Enable the SYSCFG peripheral clock*/
    1 c+ M& m' k5 A% w
  9. __HAL_RCC_SYSCFG_CLK_ENABLE(); //使能 SYSCFG 外设
    ) }& d6 A7 F4 N* v
  10. __HAL_SYSCFG_REMAPMEMORY_SRAM();//将内部 SRAM 映射到 0x00000000 地址/ N; S% L" {3 F$ [6 e- l) o
复制代码
4 l/ [) P0 B0 M  D8 u" B( Q
. A% y* s3 H# ]% o; J
。。。。。。 后面为用户功能代码。。。。。。
; G. X2 X6 t& O9 P
9 E) W; t' M7 J* B上面代码中绿色语句就是实现中断矢量表从内部 flash 到内部 RAM 的拷贝,而红色语句则是为了实现将程序执行的 0 地址域的重映射,即将程序运行的 0 地址从内部 flash 的0x8000000 通过重映射机制切换到 0x20000000,为的是在 APP1 区发生中断时 CPU 能从正确的地方准确获取相应中断矢量地址去执行中断服务程序。
- ^1 O$ B, j; ^7 Z- p. h
9 Q9 u* P; S: I" @" B3 d* h到此,从 BOOT 区跳转到 APP1 区就算完成了。
/ ]7 B: i+ S4 B( U
( i5 Z9 K7 h; g+ x, Z, y从【APP 区】调转到新【APP 区】 * C! _8 f. M5 O8 a' C

$ ?4 H6 k5 L0 n+ h" D那么,如果想从 APP1 区跳转到另外 APP2 代码区呢?这个跟从 BOOT 区跳转到 APP1 区类似。在 APP1 区的跳转代码这里就不说了,地址给对、代码写对就好。APP2 区的代码也同样必须做中断矢量表的拷贝和 0 地址域的重映射。但因为在 APP1 代码里已经做过了 0 地址的重映射,所以就不必重复做了。 3 x+ B- `3 T+ ~& H" r
7 {* q  w4 j9 P* F) e7 o: e
假定 APP2 代码区的内部 flash 空间安排在为 0x8008000—0x800C000。则 MDK 里 memory布局配置如下:: N8 F0 J" o, p+ L  i2 z

4 \" c' |6 U4 x7 u- u' \ )`S(%VOK7T7X45BX3C`C6.png # j( Y8 z7 S5 g! h7 ?: ]; L
0 l8 u8 i* v! ^/ E3 T- l# O* {
从【APP 区】跳转到【BOOT 区】5 c& Q' w% k5 k
5 P+ V! n/ k5 X. [' R% S
有时我们还希望或需要程序能从 APP 区跳回用户 BOOT 区,那如何操作呢?对于 STM32F0芯片而言,程序执行区从 APP 区跳回 BOOT 区跟从 BOOT 区跳到 APP 区还不太一样,经常有人在这个跳转过程中卡壳,对于跳得出而跳不回感到难以理解。
% L4 c$ d4 R! y. P& k
, \9 i0 |7 t3 Z2 H& @  X! i假设从 APP2 区跳回 BOOT 区,在 APP2 区做跳转准备时除了给定正确的跳转地址外,另一个要做的就是将之前通过重映射将 0 地址程序空间从内部 SRAM 切换回内部 flash 区。实际应用中,我们往往因为忽视了这点,跳回去后一碰到中断就问题来了。另外,从 APP8 K( S& B4 @/ ?6 V" [4 r4 y& V9 R
区跳回 BOOT 区无须矢量表的拷贝操作。所以在 APP2 区执行跳转前需将 0 地址重映射回内部 flash 空间,通过运行如下库代码完成:
% J& o: \4 }1 {# P5 g" W/ E$ V
" i8 h1 X5 i+ Y6 E__HAL_SYSCFG_REMAPMEMORY_FLASH();
8 i6 U4 z  {) g2 V5 B6 o  I4 H' U. f' C- _( M  M4 B
几点重要经验总结0 E" l+ Z8 [9 [4 s+ i

- I' X6 G6 ]( P1 y1 D通过以上几种不同情况下操作过程的描述,我们可以知道,想要避免 STM32F0 在代码调转中出错,应该遵循以下几条关键的经验:1 x& {6 m- b& C& i+ _9 Q$ o7 s

$ X" D9 T# M: s- C 从【BOOT 区】跳转到【APP 区】,在【APP 区】要做中断矢量表的拷贝和将 0 地址从内部 flash 切换到内部 SRAM 起始地址。
) t* c. J# J9 I" j6 z# i0 A9 p# @
 从【APP 区】跳转到其它新的【APP 区】,只需在新的【APP 区】的代码里再做中断矢量表的拷贝,并保证相关存储配置的正确。
/ K; N; l3 [& ?+ n/ i
" Y0 |7 r6 a7 Y( u2 G" m 从【APP 区】跳回【BOOT 区】,该过程无矢量表的拷贝,只需将 0 地址执行域重新映射回内部flash 区。
, O, A& n9 V6 a
7 u$ ^5 ?4 U; z  C 不论从什么区跳往什么区,跳转前禁用当前用户打开过的所有中断使能、确保无未处理的中断请求存在或在跳转过程中发生中断。* B0 v# \1 F, K# e  E

+ i- w* H! a: |7 f 以上操作流程主要针对基于 COMTEX M0 内核的 STM32F0 系列芯片。7 b6 H8 o* N- o7 C+ n9 O0 c
+ |9 O9 P2 p# @5 i6 i3 K
* S3 j; k9 I( b8 U/ R( Q

) V7 r+ U  C* k9 g- Z+ |4 _. t  H
6 @& n7 y8 d7 ~) K6 U3 W( p8 \5 i2 C1 D5 f" b7 _

' Z" ~+ i) b4 P! I
5 n! t3 [4 u) s' x$ D. z2 P" p1 u$ H! _

! g5 e! \& y8 r
5 ^# H: q" f! o: N. q/ I9 j
4 ^% G1 C* `. `9 I& O+ ]  G: p
6 W( p3 l  ^, C
# \, ]+ @: ~* R4 U1 x5 V; c5 S
收藏 评论0 发布时间:2022-2-26 16:47

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版