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

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

[复制链接]
STMCU小助手 发布时间:2021-11-24 14:59
1 前言4 d: a$ Q+ `1 `! j; y- v" V
STSW-STM32116是ST官网基于标准库的针对STM32F0的USART进口IAP示例程序
& n- ^, K& E# d& ~" ?. ^工程原本是针对STM32F051,本文将介绍如何移植到STM32F070,并针对移植的过程中的问题逐个处理。& \- `# }/ j- A" F! a
6 k  H- O: k) E5 D7 g% g4 D
2 KEIL下移植
0 H) c* H! H; T0 \  iIAP程序一般分为两个,一个是IAP,一个是APP,IAP存放在内置FLASH的0x8000000的起始位置,而APP则存放在离这个位置一定距离的位置,这个距离一定是大于或等于IAP本身所占空间大小,本例子为0x8003000。
8 g5 O2 z* E3 @6 i! j3 |( x, |9 ]4 d* D  _% ^1 x9 W
下载资源后,打开STM32F0xx_AN4065_FW_V1.0.0\Project\STM32F0xx_IAP\下的binary_template工程,这个就是APP工程,首先用KEIL打开,修改device为STM32F070,) J  a# z3 x7 I% T3 A2 p. n, J
% h0 ]0 l" _- ^( f
20160728204029911.png

* `; J5 O+ U+ H3 Y. \: [" v
, I  j. i0 R' Z4 b$ M, @& i并编译,结果发现原始的公式是编译不过的,如下错误信息:! r7 a, [" u- J# p! t/ S" k
  1. linking...$ N( I5 ~" f1 ~0 P
  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.
    % i' q1 @" s/ }! v  ~
  3. Not enough information to list image symbols.% N$ b& X, X7 z, O
  4. Finished: 1 information, 0 warning and 1 error messages.
    ( A6 g2 q4 ?. l' ~/ c- P
  5. ".\STM320518_EVAL\STM320518_EVAL.axf" - 1 Error(s), 0 Warning(s)., x( X) J: g9 j# ^2 ?
  6. Target not created.3 U! l/ B- e! Z. v, ~# t$ g; R# \& E
  7. Build Time Elapsed:  00:00:08
复制代码

" p$ Z. e+ x/ h9 h, I! D: f( o- U从字面上判断为编译system_stm32f0xx.c文件生成的目标文件system_stm32f0xx.o中的数据段(.data)内的RW数据与main.o中的数据在地址0x20000000产生冲突。
+ t5 e" ^7 Y5 B  x仔细查看代码,发现main函数之前这么一段:7 C# ~. d9 O9 }" l
  1. #if   (defined ( __CC_ARM ))
    , z) }1 T  t* M5 q, h2 M4 [# P4 a- r
  2.   __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));
    1 h% x' S, b! L, r# J, r
  3. #elif (defined (__ICCARM__))( I, \: ~( T* o) G- X! @, D# H% E- ?
  4. #pragma location = 0x20000000
    4 H! _  `, ?. M* R6 P6 d- G
  5.   __no_init __IO uint32_t VectorTable[48];7 ]4 }0 {5 l6 _# W. L7 [4 q/ y! r
  6. #elif defined   (  __GNUC__  )& m3 Z  E8 \' w
  7.   __IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));
    & q& p; H) D3 ~+ F$ P
  8. #elif defined ( __TASKING__ )
    4 L/ H( M9 s$ G; P
  9.   __IO uint32_t VectorTable[48] __at(0x20000000);* W, P9 Q* @! k8 f7 s% H6 c
  10. #endif
复制代码
9 x7 F; r2 ?3 |
可见代码是要将中断向量表VectorTable强制定义在内存0x20000000上,但是此地址与system_stm32f0xx.c定义的全局变量位置有冲突。于是,需要修改避免冲突。中断向量的地址是固定的,但其他全局变量的地址可以相应地移动下,并且APP的烧录位置为0x8003000,如下图:
  b* z1 t6 E( \- L& }" Q0 x9 _$ K' P4 q5 }: p5 N" n$ t% G, m; {
20160728203625097.png

6 L" u/ j6 j  h" v7 e! P0 B
; a' V0 @( U& I( a, p  }1 w/ p! }再次编译,错误就会消失了。
" S& A" I  T+ I! W& b8 Q% p
! E2 T# `! Y# q4 W1 L另外需要将main函数内前面几行代码做些修改:+ l* b  R, M$ m, q
  1. int main(void)
    8 r: y" s& B  W9 B3 B6 `4 J
  2. {
    ! _2 A8 Q% U( P6 K
  3.   uint32_t i = 0;* i, }& m( U2 I' ^/ a; W

  4. 8 Q1 s% S5 A5 n( R% I1 s/ G
  5.   /*!< At this stage the microcontroller clock setting is already configured,
    2 \+ b6 o& z3 l2 X  v0 l
  6.        this is done through SystemInit() function which is called from startup$ |. S6 E6 s* B) V5 g, F
  7.        file (startup_stm32f0xx.s) before to branch to application main.5 \/ v9 d& I7 k( A% a+ S! N; S
  8.        To reconfigure the default setting of SystemInit() function, refer to
    9 D! E% z7 ?" b: ]
  9.        system_stm32f0xx.c file! U! d6 o0 P# r/ q1 t. S  s* x
  10.      */
    4 ^( _8 K7 D7 M  j) m8 ?8 U% x) F

  11. 5 L) m" s9 h* r7 ]' N3 g* b) H# ?
  12. /* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/  8 O0 @- ?' E( w4 N8 t
  13. ) w$ Q7 F! o5 Z0 Y, V
  14.   /* Copy the vector table from the Flash (mapped at the base of the application$ R* _, O& M. _  g) S
  15.      load address 0x08003000) to the base address of the SRAM at 0x20000000. */, l6 H: D/ ?, Q7 b% A3 N- {) c
  16.   for(i = 0; i < 48; i++)! ~; |9 r3 j/ G/ f3 C9 b
  17.   {2 Y3 H7 P( ]( L8 g
  18.     VectorTable<i> = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));( b% g5 T! u( ?  v$ p  h
  19.   </i>}4 [9 q. ^0 n' \% {. a4 f

  20. , m/ a4 Y4 [% B* j, Y
  21.   /* Enable the SYSCFG peripheral clock*/7 ^4 B% v7 W1 L1 U: X  _( A/ F
  22.   //RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE); - z! p* w/ E# U6 Q
  23.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);    //需要修改成这样+ c8 H& M  M' g
  24.   /* Remap SRAM at 0x00000000 */* l. T: J0 ]- L* F  l
  25.   SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
    " C0 G( a# \3 S2 n
  26. ' l9 J- J# k0 \) i5 _  ]
  27. /...
    2 U! F3 g* {3 D1 o# v. K* F" k
  28. }
复制代码
; U2 t/ _# v7 k# F$ j  G7 r# o
打开对应的map文件,有如下内容:; l. I' A* M" n2 G5 S9 ]0 v
  1. GPIO_PIN                                 0x08003470   Data           8  stm320518_eval.o(.constdata)0 G8 y1 l9 u1 e' f
  2.     GPIO_CLK                                 0x08003478   Data          16  stm320518_eval.o(.constdata)
    $ N0 _) f( E* s8 y5 }
  3.     BUTTON_PIN                               0x08003488   Data          14  stm320518_eval.o(.constdata)
    4 O; i; ]: \3 y) h% Z
  4.     BUTTON_CLK                               0x08003498   Data          28  stm320518_eval.o(.constdata)$ b5 Z0 B3 U0 z2 J0 i% {
  5.     BUTTON_EXTI_LINE                         0x080034b4   Data          14  stm320518_eval.o(.constdata)# o  u0 n- h* e9 ~2 U. Y6 I
  6.     BUTTON_PORT_SOURCE                       0x080034c2   Data          14  stm320518_eval.o(.constdata)
    # U- U% D8 ?$ u# M! X
  7.     BUTTON_PIN_SOURCE                        0x080034d0   Data          14  stm320518_eval.o(.constdata)
    0 c, C3 M8 X' H) ]" O8 H& B
  8.     BUTTON_IRQn                              0x080034de   Data          14  stm320518_eval.o(.constdata)
    # X& ]% ]( F& ]* f+ h, _
  9.     COM_USART_CLK                            0x080034ec   Data           4  stm320518_eval.o(.constdata)
    ; n* w3 I7 V# {4 N& Y4 }) c
  10.     COM_TX_PORT_CLK                          0x080034f0   Data           4  stm320518_eval.o(.constdata), V9 P9 H/ Y2 u4 |
  11.     COM_RX_PORT_CLK                          0x080034f4   Data           4  stm320518_eval.o(.constdata): d9 F' f. o" X7 X( w
  12.     COM_TX_PIN                               0x080034f8   Data           2  stm320518_eval.o(.constdata)
    ) b6 L& u# h# O% K7 I/ n& n3 ^2 p
  13.     COM_RX_PIN                               0x080034fa   Data           2  stm320518_eval.o(.constdata)
    7 ?$ K4 O9 x  N2 ^5 f- x9 m  a0 M/ W
  14.     COM_TX_PIN_SOURCE                        0x080034fc   Data           2  stm320518_eval.o(.constdata): t$ @5 K! @2 A4 P/ Q! D
  15.     COM_RX_PIN_SOURCE                        0x080034fe   Data           2  stm320518_eval.o(.constdata)- O; X6 l  q& A% y
  16.     COM_TX_AF                                0x08003500   Data           2  stm320518_eval.o(.constdata), D% W# M& `" w, v
  17.     COM_RX_AF                                0x08003502   Data           2  stm320518_eval.o(.constdata)
    " |" [+ i  O1 A/ ^3 j0 _; {8 e" M
  18.     Region$Table$Base                      0x08003504   Number         0  anon$obj.o(Region$Table)/ i3 u& Q3 K% q/ [7 J5 Z0 E
  19.     Region$Table$Limit                     0x08003524   Number         0  anon$obj.o(Region$Table); |$ [1 {  m4 P+ h& i' O9 {( g
  20.     VectorTable                              0x20000000   Data         192  main.o(.ARM.__AT_0x20000000)      //向量表位置为0x20000000
    ) g9 h! Z; w+ m4 i
  21.     SystemCoreClock                          0x200000c0   Data           4  system_stm32f0xx.o(.data)         //其他全局变量的起始位置为0x200000C0; |. S6 D2 O( U) ?  U# C* M
  22.     AHBPrescTable                            0x200000c4   Data          16  system_stm32f0xx.o(.data)/ O/ e- E0 I1 R
  23.     GPIO_PORT                                0x200000d4   Data          16  stm320518_eval.o(.data)
    5 c2 l- R, [8 F
  24.     BUTTON_PORT                              0x200000e4   Data          28  stm320518_eval.o(.data)
    ' n: P" U0 j. g
  25.     COM_USART                                0x20000100   Data           4  stm320518_eval.o(.data)) o: T! ?/ `& p$ f
  26.     COM_TX_PORT                              0x20000104   Data           4  stm320518_eval.o(.data)/ o' y: q2 C9 B% p8 F  k4 T
  27.     COM_RX_PORT                              0x20000108   Data           4  stm320518_eval.o(.data)
    4 i  Z2 W3 l  a# N; ~4 v0 @' i$ r
  28.     __initial_sp                             0x20000510   Data           0  startup_stm32f0xx.o(STACK)) T  D1 }5 b2 ?- c& l6 X6 O1 H
复制代码

9 H$ K3 O/ n( @# X, N如上所述,中断向量表被编译在0x20000000,内存的起始位置,而system_stm32f0xx.c下的全局变量SystemCoreClock被KEIL编译成放在紧挨着的0x200000C0的位置,与预期完全相符。分别将IAP与APP烧录进FLASH,测试可以正常运行。
* Y/ h5 w7 @2 q! ^0 A- n0 T( v3 v  k; c: G* z# t
注:在KEIL下,必须存在IAP才能调试APP!,这点是与IAR不同的。7 z' h$ u7 q7 A$ }: h1 R* u

7 l4 x. {$ A4 G! V. F5 M
- {5 ?' m# l9 u2 Y& ~+ ?5 y! K3 IAR下移植
# X; G2 S  F5 ]3 a' }6 P在IAR下的IAP没有什么特殊的,主要还是看APP的配置。( G$ o& J; ^$ ^7 x7 o. H1 f6 @

9 u1 T' M; o8 Z2 G. |* M" a使用IAR打开APP工程,修改device为STM32F070:+ n" _$ `+ V0 w+ A' w* h+ K& ~& ?

5 }  ~+ h$ g5 p6 X
20160728213900343.png

7 w4 m$ `* g" \0 m# ?0 c" V4 m* ~
; Z7 N! v+ m' ?链接配置:
+ v: X7 J9 e8 O6 X: k( Z* O  A/ C) e5 P
中断向量表:% ]1 T; v, b) g) Y
" u' @8 y5 }. L! G3 ?- K5 E
20160728213954703.png
! F% E; V8 Y. M) `" a% f5 w; B
+ s1 N# F% Z9 g2 g3 I/ O
内存映射:
) S& D* p) }% U0 B% c
; c8 T& a+ [0 T0 {
20160728214047079.png

' f0 r6 P0 Z% N& P0 ^: e0 v( |, @# r4 e  f3 u0 b
3 g  A* z9 q! W, k5 M
. t. r3 r& ~/ q3 R; _- @
如上,APP存放在FLASH的位置0x8003000,内存还是设置为:0x20000000.3 ]2 `4 G6 h; r0 Q" C! D
0 C+ t* w$ |" g( {
编译后,打开对应的map文件如下所示:
. C) g0 ^' [, S2 J9 I0 y8 f( C8 [% N: o. Y* X
  1. Entry                      Address  Size  Type      Object
    . U  H6 g3 h5 l) ?
  2. -----                      -------  ----  ----      ------7 Y' i5 q6 j& J- B
  3. .iar.init_table$Base   0x080034fc         --   Gb  - Linker created -  C+ C( b1 [- o# ^- M5 ]" @* Q
  4. .iar.init_table$Limit  0x08003510         --   Gb  - Linker created -
    $ a) P& Q, P$ {; U8 s$ C4 s5 T1 t; w' `
  5. ?main                   0x08003511        Code  Gb  cmain.o [4]
    " r( x1 F7 Q# O# n
  6. CSTACK$Base            0x200000d8         --   Gb  - Linker created -
    1 V5 ^& [5 N8 b# n
  7. CSTACK$Limit           0x200010d8         --   Gb  - Linker created -1 a7 N2 L+ C2 X
  8. Delay                   0x080031e3  0x10  Code  Gb  main.o [1]9 B& l5 W+ w6 v5 `
  9. GPIO_PIN                0x080035a0   0x8  Data  Gb  stm320518_eval.o [1]. u3 ~  x3 G. l$ D- g  X' G  f6 ~( x
  10. GPIO_PORT               0x200000c0  0x10  Data  Gb  stm320518_eval.o [1]           //stm320518_eval.c文件内的全局变量GPIO_PORT数组存放在0x200000c0( U2 w2 r' Z( [% E5 X" B
  11. HardFault_Handler       0x08003573   0x4  Code  Gb  stm32f0xx_it.o [1]+ H7 q, C; p4 u- n' n8 f
  12. NMI_Handler             0x08003571   0x2  Code  Gb  stm32f0xx_it.o [1]! S8 N) L9 Z6 `3 V5 `
  13. NVIC_SetPriority        0x080030c1  0x84  Code  Lc  main.o [1]3 l/ K0 C' G2 A. d, ]- C, x
  14. PendSV_Handler          0x08003579   0x2  Code  Gb  stm32f0xx_it.o [1]6 M. ^0 E( B! t7 }, _" T
  15. RCC_APB2PeriphClockCmd  0x08003229  0x20  Code  Gb  stm32f0xx_rcc.o [1]+ h# B9 _2 m& a5 _
  16. Region$Table$Base     0x080034fc         --   Gb  - Linker created -
    - f3 U, S# s& ~) E
  17. Region$Table$Limit    0x08003510         --   Gb  - Linker created -
    + y# i) K) N' J6 I1 }9 L
  18. STM_EVAL_LEDToggle      0x08003315  0x26  Code  Gb  stm320518_eval.o [1]1 \0 Y  e, p! o  e* F9 W5 q
  19. SVC_Handler             0x08003577   0x2  Code  Gb  stm32f0xx_it.o [1]5 X3 b: v9 a0 C" w# c% k6 Z
  20. SYSCFG_MemoryRemapConfig, h- ]5 z9 ]* i2 o8 O8 O' N& }$ N
  21.                         0x0800324d  0x14  Code  Gb  stm32f0xx_syscfg.o [1]) p: h9 ^/ C% \8 m
  22. SetSysClock             0x080033b7  0xbe  Code  Lc  system_stm32f0xx.o [1]0 A, G* o6 Y8 z5 p9 u
  23. SysTick_Config          0x08003145  0x32  Code  Lc  main.o [1]+ i8 ^, L1 ?: h
  24. SysTick_Handler         0x0800357b   0x8  Code  Gb  stm32f0xx_it.o [1]
    7 U5 u! }) k* G* v! ~+ b
  25. SystemCoreClock         0x200000d0   0x4  Data  Gb  system_stm32f0xx.o [1]
    2 M6 k% f' m  w5 z# o
  26. SystemInit              0x08003349  0x6e  Code  Gb  system_stm32f0xx.o [1]
    ' F3 Y$ S; {' w% ?
  27. TimingDelay             0x200000d4   0x4  Data  Lc  main.o [1]
    ) d. N2 Q& G/ B/ W1 V. p/ f
  28. TimingDelay_Decrement   0x080031f3  0x16  Code  Gb  main.o [1]
    * \/ J/ [( v. q5 e3 \
  29. VectorTable             0x20000000  0xc0  Data  Gb  main.o [1]           //向量表编译位置为0x200000002 G$ C/ t- E/ b8 R
  30. __aeabi_idiv0           0x08003345        Code  Gb  IntDivZer.o [4]
    7 x7 I2 `. q+ C+ L3 J
  31. __aeabi_uidiv           0x08003265        Code  Gb  I32DivModFast.o [4]2 [+ b5 K# G2 A0 [6 E! Y6 i
  32. __aeabi_uidivmod        0x08003265        Code  Gb  I32DivModFast.o [4]
    2 V3 W6 L8 V+ i
  33. __cmain                 0x08003511        Code  Gb  cmain.o [4]
    6 _; ^5 k8 ?& U) j4 {3 }% q) J
  34. __exit                  0x08003545  0x14  Code  Gb  exit.o [5]' M) V- c: S! t$ d& V' d4 @
  35. __iar_copy_init3        0x080034a5  0x30  Code  Gb  copy_init3.o [4]
    * y, A' }; G+ U  L5 @2 E, E$ v% p( W/ ?
  36. __iar_data_init3        0x080034d5  0x28  Code  Gb  data_init.o [4]
    5 z. i1 {7 D# U6 |
  37. __iar_program_start     0x08003595        Code  Gb  cstartup_M.o [4]9 L/ M$ g# @1 ?+ e0 |8 X6 Q+ M0 x
  38. __low_level_init        0x0800352b   0x4  Code  Gb  low_level_init.o [3]& q: q* A0 s2 \. f
  39. __vector_table          0x08003000        Data  Gb  startup_stm32f0xx.o [1]
    ! r- g* c# D% k8 z, i
  40. _call_main              0x0800351d        Code  Gb  cmain.o [4]
    ! j6 l/ [5 G9 O, _4 q! X) l4 {5 X* z
  41. _exit                   0x08003539        Code  Gb  cexit.o [4]
    ' j  G. O+ Y" n+ a1 q
  42. _main                   0x08003527        Code  Gb  cmain.o [4]
    # U, J2 y) o" |) E
  43. exit                    0x0800352f   0x8  Code  Gb  exit.o [3]
    - z6 N6 _' M' p0 r* w9 u
  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>
复制代码
( g  l% J+ ^# o( _
如上所示,在IAR编译下,中断向量表被编译在0x20000000,内存的起始位置,而stm320518_eval.c下的全局变量GPIO_PORT被IAR编译成放在紧挨着的0x200000C0的位置。分别将IAP与APP烧录进FLASH,测试可以正常运行。, j5 T6 l( F! {: w
4 C% H  M' N( m5 f, g( l2 K& S
注:从IAR工程的链接配置来看,并没有像KEIL那样配置RAM位置为:0x2000000,编译后的结果向量表也不会与其他全局变量相冲突,可见IAR编译器已经自动计算并避免这种冲突,不像KEIL那样会出现链接错误,以此来提示用户。' t; f1 Q7 L7 _
8 K$ t( f& F4 I7 o; k+ Z4 D# h
另外:在IAR下,在不存在IAP的情况下也是可以调试APP的,这点是KEIL所不具备的功能,看样子,IAR在细节的处理上比KEIL要好。
# X3 ]0 Q  c2 G" ^
. W# G% i& T8 _' }9 _  y* |# J  s) L& i" R# L# N! A: g3 x% K

* R9 C" B# L- a) u- [
赞 收藏 评论0 发布时间:2021-11-24 14:59

举报

0个回答

所属标签

相似技术帖

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