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

【经验分享】使用USART接口进行STM32F0的在线升级(AN4065)-基于标准库的STM32F070的IAP移植手记

[复制链接]
STMCU小助手 发布时间:2021-11-24 14:59
1 前言7 h2 B* D  E+ m) v3 r
STSW-STM32116是ST官网基于标准库的针对STM32F0的USART进口IAP示例程序
+ X7 l8 ?" A' Q8 }工程原本是针对STM32F051,本文将介绍如何移植到STM32F070,并针对移植的过程中的问题逐个处理。" O9 @# c3 C, {

) |2 A+ g# P9 k' U6 D# t
2 KEIL下移植  H3 g( `' I" B  \! A3 v5 X) z& Y
IAP程序一般分为两个,一个是IAP,一个是APP,IAP存放在内置FLASH的0x8000000的起始位置,而APP则存放在离这个位置一定距离的位置,这个距离一定是大于或等于IAP本身所占空间大小,本例子为0x8003000。
9 W! A% ~+ C3 m1 \( `, [
6 A2 E5 F. d- ^' t% p' L下载资源后,打开STM32F0xx_AN4065_FW_V1.0.0\Project\STM32F0xx_IAP\下的binary_template工程,这个就是APP工程,首先用KEIL打开,修改device为STM32F070,
* y( }) z/ o: F: Z1 v+ X- l9 b  z/ s* E" o
20160728204029911.png
: w3 D+ `) D. u- v/ r7 \0 _
, Q7 F- [! T6 G3 }9 ~0 A
并编译,结果发现原始的公式是编译不过的,如下错误信息:
) N0 m9 j4 V* S6 O% j
  1. linking...7 ]# r% w/ L% m( e3 D
  2. .\STM320518_EVAL\STM320518_EVAL.axf: Error: L6971E: system_stm32f0xx.o(.data) type RW incompatible with main.o(.ARM.__AT_0x20000000) type ZI in er RW_IRAM1.2 R; J( Q! y, Q6 i4 e
  3. Not enough information to list image symbols.% x$ E+ H* P7 l7 P. S' q) h# I; V
  4. Finished: 1 information, 0 warning and 1 error messages.
    ( b3 p: ?2 B0 f
  5. ".\STM320518_EVAL\STM320518_EVAL.axf" - 1 Error(s), 0 Warning(s).3 P7 N" ^' q  H9 m" s3 K6 X% a
  6. Target not created.  F7 E- P; b/ ]/ s) d7 w
  7. Build Time Elapsed:  00:00:08
复制代码
( \; n  u& d& L
从字面上判断为编译system_stm32f0xx.c文件生成的目标文件system_stm32f0xx.o中的数据段(.data)内的RW数据与main.o中的数据在地址0x20000000产生冲突。3 u6 s1 I$ Y) Y
仔细查看代码,发现main函数之前这么一段:; n* [/ |, y4 J- \2 S
  1. #if   (defined ( __CC_ARM ))
    ; w+ b& I8 y4 k& p. S3 P4 }! b
  2.   __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));( h; f0 n5 }5 v" K& V2 [9 A
  3. #elif (defined (__ICCARM__)). i7 `  }3 r3 y+ h9 E8 e
  4. #pragma location = 0x20000000) z% V/ u- ^4 m# w
  5.   __no_init __IO uint32_t VectorTable[48];
    / N4 }6 M3 Z; Q# c+ }1 |* o
  6. #elif defined   (  __GNUC__  )6 i3 z$ W* S' Q. O
  7.   __IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));
    ! r: _7 J; L$ p7 C5 J  W/ v
  8. #elif defined ( __TASKING__ )% F  w1 N* G- J" a0 E
  9.   __IO uint32_t VectorTable[48] __at(0x20000000);
    # A# G' T+ `2 g2 }& \  H4 h, L' o
  10. #endif
复制代码
- X4 n1 x; o) ~& |# c
可见代码是要将中断向量表VectorTable强制定义在内存0x20000000上,但是此地址与system_stm32f0xx.c定义的全局变量位置有冲突。于是,需要修改避免冲突。中断向量的地址是固定的,但其他全局变量的地址可以相应地移动下,并且APP的烧录位置为0x8003000,如下图:. v3 V) e# S8 J- q

. V. S8 ], p4 E) J" z
20160728203625097.png

& P  \1 `$ u& q* b( [( O/ H3 p
+ v. V* V, k4 D再次编译,错误就会消失了。7 h% C/ ~: ?5 \/ J7 E( f
2 b+ \; ?: {2 o: \0 `/ x5 ?* @0 L9 Y
另外需要将main函数内前面几行代码做些修改:
# B! B, N" U+ r0 d) I
  1. int main(void)' f2 i) p- Y; W7 f' {, R
  2. {
    / o$ Y9 D/ ~  q6 v- A; i& f
  3.   uint32_t i = 0;# Q+ ^4 \4 e. A1 i

  4. , v& x% O9 q+ C7 q- D
  5.   /*!< At this stage the microcontroller clock setting is already configured, . ^" _& ~( d6 `+ W9 e3 i- B1 w
  6.        this is done through SystemInit() function which is called from startup
      m. D# \8 D8 j" p/ q* K
  7.        file (startup_stm32f0xx.s) before to branch to application main.9 q" \. C# t) O( Y8 z+ G
  8.        To reconfigure the default setting of SystemInit() function, refer to4 z/ Y! E9 M  m+ V7 F7 V
  9.        system_stm32f0xx.c file  N' l  E* {! B) V4 R. S9 D6 d9 w
  10.      */ + Y8 f: X$ X% Q
  11. " ^* j, R0 B% n' ^
  12. /* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/  ; d' Z/ C3 _" Q( {$ D8 e

  13. 2 F/ V* H, {( x
  14.   /* Copy the vector table from the Flash (mapped at the base of the application9 j' L- g8 S' n# K3 t) D/ ]
  15.      load address 0x08003000) to the base address of the SRAM at 0x20000000. */
    ; Y( @3 O0 [3 Y
  16.   for(i = 0; i < 48; i++)
    & P, y7 f$ B  Y: g  y  }5 m
  17.   {; s  [. B% Q0 g
  18.     VectorTable<i> = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));
    % P. x" {, @* x# g- n
  19.   </i>}4 B2 d) B8 {1 [" _
  20. 5 U( B& U  ~2 M6 H3 _
  21.   /* Enable the SYSCFG peripheral clock*/: E" x) t; `: J- x0 B
  22.   //RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    ! z' u2 J* @5 `. M* s
  23.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);    //需要修改成这样- Q( i  ?0 R: ^' }5 Z2 f' L5 {8 L" ]4 ~
  24.   /* Remap SRAM at 0x00000000 */
    " Z$ {3 f8 N7 P% O( X) |/ w
  25.   SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);9 m2 q7 v0 X$ M8 Z# O
  26. 8 h( ~9 n& N+ f3 @1 ?6 S, N
  27. /...
    8 f) Q# t" p5 f+ U6 S+ z
  28. }
复制代码
4 y+ o1 _: K8 ?
打开对应的map文件,有如下内容:
' E/ q, q4 L& Z5 `
  1. GPIO_PIN                                 0x08003470   Data           8  stm320518_eval.o(.constdata)
    " v& Y9 V; @. @7 n% ]0 e* V) Z, i
  2.     GPIO_CLK                                 0x08003478   Data          16  stm320518_eval.o(.constdata)5 r' [7 M) B9 Q  E. b5 h
  3.     BUTTON_PIN                               0x08003488   Data          14  stm320518_eval.o(.constdata)& g, }$ C- j3 O# V. |  J
  4.     BUTTON_CLK                               0x08003498   Data          28  stm320518_eval.o(.constdata)
    1 i" D" ~! g: }0 X7 b4 }
  5.     BUTTON_EXTI_LINE                         0x080034b4   Data          14  stm320518_eval.o(.constdata)
    - \( x8 X/ G& H7 b* B
  6.     BUTTON_PORT_SOURCE                       0x080034c2   Data          14  stm320518_eval.o(.constdata)
    : I/ ]/ L) r! k! s
  7.     BUTTON_PIN_SOURCE                        0x080034d0   Data          14  stm320518_eval.o(.constdata). X: s/ \# z) L8 J/ b  ]: N& T5 B
  8.     BUTTON_IRQn                              0x080034de   Data          14  stm320518_eval.o(.constdata)
    - V' c) d, o& i0 q/ n- c# ~' i" O
  9.     COM_USART_CLK                            0x080034ec   Data           4  stm320518_eval.o(.constdata)
    ; E) W2 y4 j/ b5 k+ ^* C
  10.     COM_TX_PORT_CLK                          0x080034f0   Data           4  stm320518_eval.o(.constdata)5 g$ j) [8 D4 _4 o: B# E- D
  11.     COM_RX_PORT_CLK                          0x080034f4   Data           4  stm320518_eval.o(.constdata)
    3 t- V9 o# z* N9 z
  12.     COM_TX_PIN                               0x080034f8   Data           2  stm320518_eval.o(.constdata)! H) d+ M7 n" V
  13.     COM_RX_PIN                               0x080034fa   Data           2  stm320518_eval.o(.constdata)
    $ E7 F# T8 m( C9 {! x" A6 v
  14.     COM_TX_PIN_SOURCE                        0x080034fc   Data           2  stm320518_eval.o(.constdata)
    5 A3 y# X% \5 W9 S4 M7 w: L  ^$ _2 ]
  15.     COM_RX_PIN_SOURCE                        0x080034fe   Data           2  stm320518_eval.o(.constdata)! k0 I4 }% T, N- V  b/ d. U& O
  16.     COM_TX_AF                                0x08003500   Data           2  stm320518_eval.o(.constdata)7 I) T5 O! ?1 X6 i
  17.     COM_RX_AF                                0x08003502   Data           2  stm320518_eval.o(.constdata)8 G( X, E' F6 z$ V% i- ~, M* O
  18.     Region$Table$Base                      0x08003504   Number         0  anon$obj.o(Region$Table)8 t3 v. r! p8 O4 e
  19.     Region$Table$Limit                     0x08003524   Number         0  anon$obj.o(Region$Table)% t6 X! Q) M& L5 y( y' h' m
  20.     VectorTable                              0x20000000   Data         192  main.o(.ARM.__AT_0x20000000)      //向量表位置为0x20000000
    - q9 i8 y; X. k8 @9 P( W
  21.     SystemCoreClock                          0x200000c0   Data           4  system_stm32f0xx.o(.data)         //其他全局变量的起始位置为0x200000C08 X7 G& C/ j$ r1 t
  22.     AHBPrescTable                            0x200000c4   Data          16  system_stm32f0xx.o(.data)
    8 t$ K. N  U% y+ i* ?5 y. n% F
  23.     GPIO_PORT                                0x200000d4   Data          16  stm320518_eval.o(.data), p; b# @' i5 w0 o/ M
  24.     BUTTON_PORT                              0x200000e4   Data          28  stm320518_eval.o(.data)# L& w, S) _0 a" x
  25.     COM_USART                                0x20000100   Data           4  stm320518_eval.o(.data)! L+ c) [( f+ b  }
  26.     COM_TX_PORT                              0x20000104   Data           4  stm320518_eval.o(.data)
    - W0 x* k4 `0 N4 b
  27.     COM_RX_PORT                              0x20000108   Data           4  stm320518_eval.o(.data)" z8 @" m; r/ H$ `$ K
  28.     __initial_sp                             0x20000510   Data           0  startup_stm32f0xx.o(STACK)1 B/ ?6 e! s. C, z6 u4 u9 V
复制代码

) ?8 c' I# M# c, A3 F如上所述,中断向量表被编译在0x20000000,内存的起始位置,而system_stm32f0xx.c下的全局变量SystemCoreClock被KEIL编译成放在紧挨着的0x200000C0的位置,与预期完全相符。分别将IAP与APP烧录进FLASH,测试可以正常运行。  C% w1 r/ _% E* Y+ p! g

: g% T& q0 m7 J) }" H1 T注:在KEIL下,必须存在IAP才能调试APP!,这点是与IAR不同的。
5 d! e! J1 ]& x# V) s1 I7 x2 `
( M2 W" u: l3 w' A) U! o% v$ x6 p. k5 {9 n0 G2 N* C6 M1 e3 j( r( Y
3 IAR下移植8 y* B" }* d) `
在IAR下的IAP没有什么特殊的,主要还是看APP的配置。
; M4 y1 M. f: i, b- _/ C+ c1 K9 [3 C3 @
使用IAR打开APP工程,修改device为STM32F070:
  u" |6 T- X; M$ e+ b2 c* [
5 O/ e) N2 I9 J6 [( {/ J
20160728213900343.png

8 Y8 G8 b7 i; G* D* m
. }- a: k9 g) a( [% F链接配置:$ l- V: i5 O9 F3 S
5 f- G5 ~. D( {1 }$ q, E0 Q- D
中断向量表:
9 q# I" k# @: J1 O- I) U1 d1 I
0 _+ S! ]1 F6 Z. D( K+ [$ T) c
20160728213954703.png
* M2 K6 u: t6 {8 v% _4 k! o

. |9 [7 Y+ T3 a# k- m内存映射:; F7 O: N3 I& W8 u# R8 J

: C+ Y/ i) t% `8 @+ G
20160728214047079.png

: f8 y/ t, K3 ~/ W& `& a& h) H& }5 O3 L$ n0 P2 A6 N" ]8 Y1 @8 z9 E

, ?/ E* ~+ S' t( [- M0 Q) i8 K; E* f8 s' w, W
如上,APP存放在FLASH的位置0x8003000,内存还是设置为:0x20000000.
0 E  P$ o' @% o, ?* q5 P1 _( p2 d; T: v4 A! i3 p/ ~
编译后,打开对应的map文件如下所示:
' `2 U# O0 o# D" \9 V1 U* n" r) i
  1. Entry                      Address  Size  Type      Object
    * T# J+ n( `  N
  2. -----                      -------  ----  ----      ------4 z, S4 S. G, a6 U& L2 s
  3. .iar.init_table$Base   0x080034fc         --   Gb  - Linker created -
    7 t, H# B, h4 [) ~" P# M
  4. .iar.init_table$Limit  0x08003510         --   Gb  - Linker created -* j+ P& V* V& n1 g
  5. ?main                   0x08003511        Code  Gb  cmain.o [4]
    4 e9 I# G$ i: Q( a& f% {# D
  6. CSTACK$Base            0x200000d8         --   Gb  - Linker created -
    , I. F: W% l+ G( H, }% }) y, W+ n
  7. CSTACK$Limit           0x200010d8         --   Gb  - Linker created -
    1 w- K" ]2 q2 V3 l
  8. Delay                   0x080031e3  0x10  Code  Gb  main.o [1]2 B. I" \- T: \- b% Z
  9. GPIO_PIN                0x080035a0   0x8  Data  Gb  stm320518_eval.o [1]
    8 N( S% g' ]6 e- I
  10. GPIO_PORT               0x200000c0  0x10  Data  Gb  stm320518_eval.o [1]           //stm320518_eval.c文件内的全局变量GPIO_PORT数组存放在0x200000c08 ~8 `; z! d. D- y! [9 H
  11. HardFault_Handler       0x08003573   0x4  Code  Gb  stm32f0xx_it.o [1]
    5 b1 G) P) Z0 m# w
  12. NMI_Handler             0x08003571   0x2  Code  Gb  stm32f0xx_it.o [1]
    % k* B; n; I+ Y0 A* J
  13. NVIC_SetPriority        0x080030c1  0x84  Code  Lc  main.o [1]
    5 z/ \7 W3 E2 x3 e' R6 }( y0 e: N) e" r
  14. PendSV_Handler          0x08003579   0x2  Code  Gb  stm32f0xx_it.o [1]8 y  g1 t0 N$ \( f9 d9 u& q
  15. RCC_APB2PeriphClockCmd  0x08003229  0x20  Code  Gb  stm32f0xx_rcc.o [1]
    ; i" C5 T$ Z! }7 x6 q& y
  16. Region$Table$Base     0x080034fc         --   Gb  - Linker created -
    9 A% x  _+ `; B+ b  Z6 @% b
  17. Region$Table$Limit    0x08003510         --   Gb  - Linker created -+ ?$ A9 \+ Z/ \2 Z
  18. STM_EVAL_LEDToggle      0x08003315  0x26  Code  Gb  stm320518_eval.o [1]3 t8 j9 s9 M# Q% F
  19. SVC_Handler             0x08003577   0x2  Code  Gb  stm32f0xx_it.o [1]
    0 y2 |/ i# L8 [% J. p( B
  20. SYSCFG_MemoryRemapConfig( f! V: i/ n5 I  m6 {
  21.                         0x0800324d  0x14  Code  Gb  stm32f0xx_syscfg.o [1]/ K/ O( c/ r: U8 K+ W
  22. SetSysClock             0x080033b7  0xbe  Code  Lc  system_stm32f0xx.o [1]3 M( l) ^' B! W0 U4 I; {- i% a
  23. SysTick_Config          0x08003145  0x32  Code  Lc  main.o [1]8 S; j* ]& p9 y2 e' F
  24. SysTick_Handler         0x0800357b   0x8  Code  Gb  stm32f0xx_it.o [1]
      c( e4 Z. W0 E& _8 [" S- ]$ M* j
  25. SystemCoreClock         0x200000d0   0x4  Data  Gb  system_stm32f0xx.o [1]6 D7 ~0 }' m# s1 I' P
  26. SystemInit              0x08003349  0x6e  Code  Gb  system_stm32f0xx.o [1]$ ?4 R! ]3 u9 i( @* ]3 ~: Z
  27. TimingDelay             0x200000d4   0x4  Data  Lc  main.o [1]0 l# i) H3 B9 G( @) I
  28. TimingDelay_Decrement   0x080031f3  0x16  Code  Gb  main.o [1]5 A, P! s8 {. I0 G8 V( j, G/ u, L& n
  29. VectorTable             0x20000000  0xc0  Data  Gb  main.o [1]           //向量表编译位置为0x20000000
    3 t6 ?( H' t* P7 f$ p8 E$ e
  30. __aeabi_idiv0           0x08003345        Code  Gb  IntDivZer.o [4]1 u* y) c; E, N4 A0 F
  31. __aeabi_uidiv           0x08003265        Code  Gb  I32DivModFast.o [4]+ c/ l6 l9 z% p& A
  32. __aeabi_uidivmod        0x08003265        Code  Gb  I32DivModFast.o [4]
    7 i" v1 y" ]5 l- U) z
  33. __cmain                 0x08003511        Code  Gb  cmain.o [4]
      _# h" H4 k* L
  34. __exit                  0x08003545  0x14  Code  Gb  exit.o [5]
    + ~3 I# @( q) V" l3 j
  35. __iar_copy_init3        0x080034a5  0x30  Code  Gb  copy_init3.o [4]
    7 A( S! d6 o- T8 m3 M
  36. __iar_data_init3        0x080034d5  0x28  Code  Gb  data_init.o [4]; E  Y% G) `- B
  37. __iar_program_start     0x08003595        Code  Gb  cstartup_M.o [4]
    # R7 Y3 s7 b! H6 [( U
  38. __low_level_init        0x0800352b   0x4  Code  Gb  low_level_init.o [3]
    # N5 m* E! o% e0 R) R# |
  39. __vector_table          0x08003000        Data  Gb  startup_stm32f0xx.o [1]
    % ?+ M& r$ a* a4 q9 o
  40. _call_main              0x0800351d        Code  Gb  cmain.o [4]" E! d' o: j, R$ x4 a& ^1 p1 `: x
  41. _exit                   0x08003539        Code  Gb  cexit.o [4]
    - m5 k# C9 M8 o7 F, @" K5 h
  42. _main                   0x08003527        Code  Gb  cmain.o [4]" M( f% z# d) J! w1 a4 y
  43. exit                    0x0800352f   0x8  Code  Gb  exit.o [3]2 H( ^# v. H) S
  44. main                   <span style="background-color: rgb(255, 255, 255);"> </span><span style="background-color: rgb(255, 255, 255);">   0x08003177  0x6c  Code  Gb  main.o [1]</span>
复制代码

9 X2 r9 X( C+ U1 X如上所示,在IAR编译下,中断向量表被编译在0x20000000,内存的起始位置,而stm320518_eval.c下的全局变量GPIO_PORT被IAR编译成放在紧挨着的0x200000C0的位置。分别将IAP与APP烧录进FLASH,测试可以正常运行。
/ [5 u& |! F5 H) s5 Q" R' l
, W$ S5 c/ `7 x注:从IAR工程的链接配置来看,并没有像KEIL那样配置RAM位置为:0x2000000,编译后的结果向量表也不会与其他全局变量相冲突,可见IAR编译器已经自动计算并避免这种冲突,不像KEIL那样会出现链接错误,以此来提示用户。
7 p2 t( o8 u* |/ e2 S: ?; O, H# I) H( F8 e4 y+ e4 `  T
另外:在IAR下,在不存在IAP的情况下也是可以调试APP的,这点是KEIL所不具备的功能,看样子,IAR在细节的处理上比KEIL要好。
4 A7 `7 G* V7 p# e3 x9 O4 j3 w/ C7 _
0 k  M2 W2 I' k- I* n
0 R; p! P! J. Y* a* a9 I
收藏 评论0 发布时间:2021-11-24 14:59

举报

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