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

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

[复制链接]
STMCU小助手 发布时间:2021-11-24 14:59
1 前言
2 D5 s' f/ h9 n4 b( {( {STSW-STM32116是ST官网基于标准库的针对STM32F0的USART进口IAP示例程序
3 V% E2 j, s% F2 f  V8 U工程原本是针对STM32F051,本文将介绍如何移植到STM32F070,并针对移植的过程中的问题逐个处理。
3 ?2 G4 E; e" Q0 O; h& {6 `6 M% s+ k' O* T6 _+ F- O
2 KEIL下移植9 k& P% F/ a, I- Z5 E
IAP程序一般分为两个,一个是IAP,一个是APP,IAP存放在内置FLASH的0x8000000的起始位置,而APP则存放在离这个位置一定距离的位置,这个距离一定是大于或等于IAP本身所占空间大小,本例子为0x8003000。
, G+ Q5 ^2 ~5 c) w+ C
" j7 o+ n+ T! u% Q下载资源后,打开STM32F0xx_AN4065_FW_V1.0.0\Project\STM32F0xx_IAP\下的binary_template工程,这个就是APP工程,首先用KEIL打开,修改device为STM32F070,
: E! y, D- x6 ]
4 z4 u& x5 k/ c+ j/ t% f4 x' A
20160728204029911.png
" a( Y5 b8 {, X4 @7 f
# D* T: C, i1 p3 F/ J( B, |- F4 l
并编译,结果发现原始的公式是编译不过的,如下错误信息:+ a) t$ M3 m- e& ^1 f, @7 R0 Z; X
  1. linking...
    . l9 g0 }' k, I9 A6 z, J. [1 s
  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.
    0 F- U( u# ?' X: {
  3. Not enough information to list image symbols.0 K6 n6 g5 Y0 w( M2 U0 @
  4. Finished: 1 information, 0 warning and 1 error messages.
    * S; m. k% {; ~; \8 M
  5. ".\STM320518_EVAL\STM320518_EVAL.axf" - 1 Error(s), 0 Warning(s).) ~9 V6 p, J, Y" g' ]3 J* U
  6. Target not created.
    / G8 j! B! b$ v" c
  7. Build Time Elapsed:  00:00:08
复制代码
6 R7 S' S! s4 ]# N4 E
从字面上判断为编译system_stm32f0xx.c文件生成的目标文件system_stm32f0xx.o中的数据段(.data)内的RW数据与main.o中的数据在地址0x20000000产生冲突。. U4 G& ]0 G0 s) |$ ?: G6 ^/ I! l' D
仔细查看代码,发现main函数之前这么一段:/ o- f$ a" S( [7 r7 ]1 N
  1. #if   (defined ( __CC_ARM ))
    $ l- R, |# G8 a8 n+ m  z
  2.   __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));5 F! _. p' K. \# W
  3. #elif (defined (__ICCARM__))% n- d2 _2 X2 u7 J% Y- i' ^( F2 v
  4. #pragma location = 0x20000000+ v4 K0 v* T1 Z* f3 `- }
  5.   __no_init __IO uint32_t VectorTable[48];
    . {( a/ C7 ~5 E' U# j8 W
  6. #elif defined   (  __GNUC__  )% k3 E$ t0 z' ?
  7.   __IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));  t  n3 A7 d; _7 i6 S
  8. #elif defined ( __TASKING__ )' b" c, V  F8 o9 U: Z
  9.   __IO uint32_t VectorTable[48] __at(0x20000000);6 n* W+ v# A" R4 E6 f) z; |
  10. #endif
复制代码
# ?3 w/ ^* K+ F( c+ p* z
可见代码是要将中断向量表VectorTable强制定义在内存0x20000000上,但是此地址与system_stm32f0xx.c定义的全局变量位置有冲突。于是,需要修改避免冲突。中断向量的地址是固定的,但其他全局变量的地址可以相应地移动下,并且APP的烧录位置为0x8003000,如下图:/ N- B1 d; t. j

; t! o' s- Y1 }0 e, P$ ]
20160728203625097.png
( @  ]7 S: p; f" ~. n$ @& B1 \
4 B) F% y! G  ?7 @
再次编译,错误就会消失了。
6 H* |( i  [/ x+ w% @; V/ U6 K/ @8 P5 Q% e  I+ g
另外需要将main函数内前面几行代码做些修改:
2 L9 V: t) I5 F3 @
  1. int main(void)' Z- ~- n% c2 I6 N* U/ a" ]$ v4 ]
  2. {& ?  S; t: i1 @" j1 _6 U3 D
  3.   uint32_t i = 0;6 x, @: C; p- x( |5 t$ z7 u
  4. ( u* Q* u- d) ~
  5.   /*!< At this stage the microcontroller clock setting is already configured, ; ]% n( [: X/ G6 c: Y# }( n( @
  6.        this is done through SystemInit() function which is called from startup4 X4 E+ a- X4 R4 m6 f
  7.        file (startup_stm32f0xx.s) before to branch to application main.
    4 \! Q* T) F- H( y: T
  8.        To reconfigure the default setting of SystemInit() function, refer to4 ~# Q) A; W6 U) m! q
  9.        system_stm32f0xx.c file5 @. B) o8 J+ m8 q$ }$ T# Q
  10.      */ & }' t8 `; q( H+ Q

  11. 8 ?5 w4 p- f1 ~) H' {
  12. /* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/  7 J( B6 |' D( V9 e( B

  13. 7 ~$ w) Z8 J4 d# g( M5 [& d
  14.   /* Copy the vector table from the Flash (mapped at the base of the application  d& [/ Q* @4 S
  15.      load address 0x08003000) to the base address of the SRAM at 0x20000000. */) P; I* e$ u4 R$ w+ s! N
  16.   for(i = 0; i < 48; i++)& s6 L/ Y: W/ y: Q6 [8 i! g
  17.   {
    3 L4 Y. R6 q, i* ^+ P
  18.     VectorTable<i> = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));
    * I( Q" U; P# D, I" u0 u
  19.   </i>}# C+ Q0 u3 [: X

  20. - q7 S  x8 D! e! t% r
  21.   /* Enable the SYSCFG peripheral clock*/
    - Z5 f  E* c6 S" G
  22.   //RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    # J! x6 Q- y6 c* L% F6 X
  23.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);    //需要修改成这样7 C: ]& D3 D- K6 Q9 G! n5 \- V
  24.   /* Remap SRAM at 0x00000000 */
    ( t. ?+ J  W; C
  25.   SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
    3 n4 `6 O- a( X- l$ p

  26. * `1 ~  M% |3 _8 {5 S
  27. /...( E" s) C/ W8 A' v# X
  28. }
复制代码
: K- Y) G8 z& \  ]+ L2 W
打开对应的map文件,有如下内容:
6 D$ d$ \& I+ Z& t) |
  1. GPIO_PIN                                 0x08003470   Data           8  stm320518_eval.o(.constdata)
    ' ^1 A# Q0 y0 [! O
  2.     GPIO_CLK                                 0x08003478   Data          16  stm320518_eval.o(.constdata)' c( I. |/ i8 M7 g- j, u, F
  3.     BUTTON_PIN                               0x08003488   Data          14  stm320518_eval.o(.constdata)6 e- a0 ~& m. q6 d) j3 Y
  4.     BUTTON_CLK                               0x08003498   Data          28  stm320518_eval.o(.constdata)1 U5 _9 n# Z( H+ X# A3 U. G
  5.     BUTTON_EXTI_LINE                         0x080034b4   Data          14  stm320518_eval.o(.constdata)
    2 s; ?4 x8 E4 B3 f5 M- z( a+ h0 [
  6.     BUTTON_PORT_SOURCE                       0x080034c2   Data          14  stm320518_eval.o(.constdata)8 d' Z  @4 ]& P. m7 x
  7.     BUTTON_PIN_SOURCE                        0x080034d0   Data          14  stm320518_eval.o(.constdata)
    ( \( \8 J5 g" u5 o. z2 p  @+ R5 A
  8.     BUTTON_IRQn                              0x080034de   Data          14  stm320518_eval.o(.constdata)
    2 E; Z* M3 K( Z
  9.     COM_USART_CLK                            0x080034ec   Data           4  stm320518_eval.o(.constdata)2 Q/ h+ K: c# Z) o8 Y
  10.     COM_TX_PORT_CLK                          0x080034f0   Data           4  stm320518_eval.o(.constdata)0 ^7 `0 f! ?5 @) T  C& P% i  j
  11.     COM_RX_PORT_CLK                          0x080034f4   Data           4  stm320518_eval.o(.constdata)8 Z, ~! g1 B5 Y7 V  f& \% D1 B' y: X
  12.     COM_TX_PIN                               0x080034f8   Data           2  stm320518_eval.o(.constdata)( ]. \! l- N4 J, Q
  13.     COM_RX_PIN                               0x080034fa   Data           2  stm320518_eval.o(.constdata)
    # q8 p5 j* ]* T6 E0 N$ E! M3 S
  14.     COM_TX_PIN_SOURCE                        0x080034fc   Data           2  stm320518_eval.o(.constdata). n: X; S5 {2 g
  15.     COM_RX_PIN_SOURCE                        0x080034fe   Data           2  stm320518_eval.o(.constdata)! ]+ P" T8 }* Z( }/ e
  16.     COM_TX_AF                                0x08003500   Data           2  stm320518_eval.o(.constdata)6 V0 _# U) I+ `! S% q
  17.     COM_RX_AF                                0x08003502   Data           2  stm320518_eval.o(.constdata)% O# u- I+ c* q% p4 G2 p, v
  18.     Region$Table$Base                      0x08003504   Number         0  anon$obj.o(Region$Table)
    * v7 F0 v9 n9 H, v, ^2 z& @3 v! V
  19.     Region$Table$Limit                     0x08003524   Number         0  anon$obj.o(Region$Table)0 B, I1 B) D, \! ]$ r' ~
  20.     VectorTable                              0x20000000   Data         192  main.o(.ARM.__AT_0x20000000)      //向量表位置为0x200000005 J1 a. s% v+ x
  21.     SystemCoreClock                          0x200000c0   Data           4  system_stm32f0xx.o(.data)         //其他全局变量的起始位置为0x200000C0* `: w. r& A9 G; l$ K# `# ~
  22.     AHBPrescTable                            0x200000c4   Data          16  system_stm32f0xx.o(.data), J3 _# _6 e; |6 i+ J, o+ `
  23.     GPIO_PORT                                0x200000d4   Data          16  stm320518_eval.o(.data)6 g# s7 o$ S8 N" @" b
  24.     BUTTON_PORT                              0x200000e4   Data          28  stm320518_eval.o(.data)6 r! F0 I- P4 `3 V7 @6 U  ~
  25.     COM_USART                                0x20000100   Data           4  stm320518_eval.o(.data)
    . k) S. c9 ?/ @! z
  26.     COM_TX_PORT                              0x20000104   Data           4  stm320518_eval.o(.data)
    9 m& ~+ j2 P# D5 d0 P4 E
  27.     COM_RX_PORT                              0x20000108   Data           4  stm320518_eval.o(.data)
    : L3 ^! A, x. b$ V
  28.     __initial_sp                             0x20000510   Data           0  startup_stm32f0xx.o(STACK), i6 ?1 A8 z3 G: C: @/ u
复制代码
; ?0 z, M1 g1 T7 {3 F
如上所述,中断向量表被编译在0x20000000,内存的起始位置,而system_stm32f0xx.c下的全局变量SystemCoreClock被KEIL编译成放在紧挨着的0x200000C0的位置,与预期完全相符。分别将IAP与APP烧录进FLASH,测试可以正常运行。6 E9 F4 ^5 r/ e8 F  p
8 M3 `, t# I- Z9 C% n$ C# K
注:在KEIL下,必须存在IAP才能调试APP!,这点是与IAR不同的。1 c* \* y" D* O% n

4 P2 k7 F: T$ I3 a; L" T- D0 x& }
) K" T; k' t$ |. Q3 IAR下移植
( L  l  \/ L' o8 R+ P在IAR下的IAP没有什么特殊的,主要还是看APP的配置。
8 H( `1 g& l) A7 Z$ U& t
% h0 j$ C: t' {9 S- D' A( ^( N( G, X使用IAR打开APP工程,修改device为STM32F070:
- ]9 e6 b" q9 [# N1 D/ Z" }$ I: A; N; D0 y
20160728213900343.png

1 l" I: k# ?6 s. W7 N7 A1 }+ W( ^& Q0 j" y2 z! @  R
链接配置:# G9 h+ Q; }  M0 V8 `9 w  p
) w0 B; N5 a0 I; i$ l+ P
中断向量表:' |+ u- h' K% N) j
2 v- b; C" s6 ~- ]% b$ ~# w( o
20160728213954703.png

8 R+ C7 K8 q# \2 o1 f$ D: n% G- _2 }% r. x3 n" f' D8 n
内存映射:
( N% b% G! E& g- k
2 T+ t7 ?. F9 R% R8 T1 x7 N
20160728214047079.png

& H6 w3 q6 O1 W; B, u8 |5 ~0 n: c+ r1 n- F% r
/ o: T- Y2 Q/ t- i

7 [" \. b* J% i2 G如上,APP存放在FLASH的位置0x8003000,内存还是设置为:0x20000000.
6 I* ]1 z/ |/ J* |& H1 P5 {2 c$ _- C' \8 k5 @' z' a! V
编译后,打开对应的map文件如下所示:
9 `9 p1 y; o! a4 f! b! d1 @9 c% w' o' ^! O. h; D
  1. Entry                      Address  Size  Type      Object
    ( g+ A3 o% L: w8 J
  2. -----                      -------  ----  ----      ------
    ; j  ~1 q% j+ a5 m2 |
  3. .iar.init_table$Base   0x080034fc         --   Gb  - Linker created -. Z. p9 I. ~2 l' K8 G# Z
  4. .iar.init_table$Limit  0x08003510         --   Gb  - Linker created -
    - h3 c9 b) y/ q, g, h
  5. ?main                   0x08003511        Code  Gb  cmain.o [4]
    # J" A3 c5 F' n+ b+ j/ I, u
  6. CSTACK$Base            0x200000d8         --   Gb  - Linker created -" [$ ^! I& E5 ^! G3 g3 o2 c! b0 J
  7. CSTACK$Limit           0x200010d8         --   Gb  - Linker created -
    6 N$ p  c: P* H; @
  8. Delay                   0x080031e3  0x10  Code  Gb  main.o [1]
    ( o; {; `; J5 V* x. L
  9. GPIO_PIN                0x080035a0   0x8  Data  Gb  stm320518_eval.o [1]" q, a9 c6 G- B' U6 G3 [
  10. GPIO_PORT               0x200000c0  0x10  Data  Gb  stm320518_eval.o [1]           //stm320518_eval.c文件内的全局变量GPIO_PORT数组存放在0x200000c0
    8 W8 J% y9 u' I! m
  11. HardFault_Handler       0x08003573   0x4  Code  Gb  stm32f0xx_it.o [1]
    ' O9 C$ b5 i5 P( b- u, N
  12. NMI_Handler             0x08003571   0x2  Code  Gb  stm32f0xx_it.o [1]6 s) T( b/ T1 \
  13. NVIC_SetPriority        0x080030c1  0x84  Code  Lc  main.o [1]
    ; }, D/ Y. D; j
  14. PendSV_Handler          0x08003579   0x2  Code  Gb  stm32f0xx_it.o [1], b9 d& T3 i9 I: F6 L
  15. RCC_APB2PeriphClockCmd  0x08003229  0x20  Code  Gb  stm32f0xx_rcc.o [1]* a) _, G5 b% ]( n
  16. Region$Table$Base     0x080034fc         --   Gb  - Linker created -
    - U3 Q3 W1 v( G, ^+ s" C
  17. Region$Table$Limit    0x08003510         --   Gb  - Linker created -
    + U& Z# F7 C' X1 I3 s8 l6 R6 g
  18. STM_EVAL_LEDToggle      0x08003315  0x26  Code  Gb  stm320518_eval.o [1]
    3 V) B% ?: J4 {1 w% @4 k
  19. SVC_Handler             0x08003577   0x2  Code  Gb  stm32f0xx_it.o [1]/ x7 D' S2 T6 E/ h
  20. SYSCFG_MemoryRemapConfig
    0 N$ S2 q/ Z" n2 V
  21.                         0x0800324d  0x14  Code  Gb  stm32f0xx_syscfg.o [1]
    5 P" {6 c! ~! o# \
  22. SetSysClock             0x080033b7  0xbe  Code  Lc  system_stm32f0xx.o [1]
    & e2 `/ L/ l; g: Q' X4 r8 }% x
  23. SysTick_Config          0x08003145  0x32  Code  Lc  main.o [1]
    % a) p' o3 A  j6 n1 a3 J+ r
  24. SysTick_Handler         0x0800357b   0x8  Code  Gb  stm32f0xx_it.o [1]4 q5 @) R& z* X! f
  25. SystemCoreClock         0x200000d0   0x4  Data  Gb  system_stm32f0xx.o [1]
    4 U, A2 X7 i+ ]9 Q5 Z0 f
  26. SystemInit              0x08003349  0x6e  Code  Gb  system_stm32f0xx.o [1]9 s* Z2 o+ K) O1 M
  27. TimingDelay             0x200000d4   0x4  Data  Lc  main.o [1]
    3 _7 z4 ^3 @' X1 g
  28. TimingDelay_Decrement   0x080031f3  0x16  Code  Gb  main.o [1]
    ) M0 y4 M. H* ]9 k: E; l% K$ S
  29. VectorTable             0x20000000  0xc0  Data  Gb  main.o [1]           //向量表编译位置为0x200000008 E. \: F; y& K- H& i9 n
  30. __aeabi_idiv0           0x08003345        Code  Gb  IntDivZer.o [4]3 b3 a9 Z& W) U1 V( f  N2 u
  31. __aeabi_uidiv           0x08003265        Code  Gb  I32DivModFast.o [4]
    ; S, W4 B2 l% }- E( ~
  32. __aeabi_uidivmod        0x08003265        Code  Gb  I32DivModFast.o [4]
    : l- M- G1 ~7 `: R
  33. __cmain                 0x08003511        Code  Gb  cmain.o [4]
    " W. m' Z1 p. y  L3 \
  34. __exit                  0x08003545  0x14  Code  Gb  exit.o [5]! D: D" a; ]! L, R
  35. __iar_copy_init3        0x080034a5  0x30  Code  Gb  copy_init3.o [4]
    0 d& W" U: v0 V) x
  36. __iar_data_init3        0x080034d5  0x28  Code  Gb  data_init.o [4]
    9 @' {5 |; n" i' B2 j, m
  37. __iar_program_start     0x08003595        Code  Gb  cstartup_M.o [4]. q$ L: `! t9 B$ _2 q
  38. __low_level_init        0x0800352b   0x4  Code  Gb  low_level_init.o [3]1 X0 y2 ^6 \0 t% r. E. ]
  39. __vector_table          0x08003000        Data  Gb  startup_stm32f0xx.o [1]
    ( Z! Z. a# Z$ v1 F5 f) J# P5 I
  40. _call_main              0x0800351d        Code  Gb  cmain.o [4]
    . t+ p+ f; Q! A, }) W$ a
  41. _exit                   0x08003539        Code  Gb  cexit.o [4]. x+ ~: f' n% q% R# r* U- A5 h
  42. _main                   0x08003527        Code  Gb  cmain.o [4]
      @" \: k7 ^. U. S$ R) v9 ^# w* [
  43. exit                    0x0800352f   0x8  Code  Gb  exit.o [3]) k5 k: r1 l! X7 r  R
  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>
复制代码

; d3 ]5 V; R; M8 p* L如上所示,在IAR编译下,中断向量表被编译在0x20000000,内存的起始位置,而stm320518_eval.c下的全局变量GPIO_PORT被IAR编译成放在紧挨着的0x200000C0的位置。分别将IAP与APP烧录进FLASH,测试可以正常运行。5 p7 u8 @/ E; z; n% e
5 K2 V/ h# N+ L1 t" F* d
注:从IAR工程的链接配置来看,并没有像KEIL那样配置RAM位置为:0x2000000,编译后的结果向量表也不会与其他全局变量相冲突,可见IAR编译器已经自动计算并避免这种冲突,不像KEIL那样会出现链接错误,以此来提示用户。
) Q  }0 m' l+ m( J. B
9 j; D0 S1 h) _2 F4 ?' D另外:在IAR下,在不存在IAP的情况下也是可以调试APP的,这点是KEIL所不具备的功能,看样子,IAR在细节的处理上比KEIL要好。
& z& ?/ w) ~; B/ t, Q
) U+ C1 h: D9 ]" P$ p$ t- z% L/ q! e; v

' m$ \( H, W0 [: y% r$ Y, X
赞 收藏 评论0 发布时间:2021-11-24 14:59

举报

0个回答

所属标签

相似技术帖

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