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

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

[复制链接]
STMCU小助手 发布时间:2021-11-24 14:59
1 前言7 a4 t7 Q. r3 c/ o/ f. N
STSW-STM32116是ST官网基于标准库的针对STM32F0的USART进口IAP示例程序
+ `4 Q  a8 i9 M1 J, V. B9 t2 X工程原本是针对STM32F051,本文将介绍如何移植到STM32F070,并针对移植的过程中的问题逐个处理。4 D/ u+ r& s8 K1 L; Z
) O* _! Z+ G% a* a! _" ]6 a" v
2 KEIL下移植8 e3 o* F$ A* i9 n* b$ {; l9 v
IAP程序一般分为两个,一个是IAP,一个是APP,IAP存放在内置FLASH的0x8000000的起始位置,而APP则存放在离这个位置一定距离的位置,这个距离一定是大于或等于IAP本身所占空间大小,本例子为0x8003000。7 a& B& d- B" C! [

& R  M2 Y2 u! O2 I6 m% {/ P下载资源后,打开STM32F0xx_AN4065_FW_V1.0.0\Project\STM32F0xx_IAP\下的binary_template工程,这个就是APP工程,首先用KEIL打开,修改device为STM32F070,0 R% P2 R6 L- c' t4 P+ P: Y7 O6 l

7 t1 Y' l" t8 o. e' ~
20160728204029911.png
; n8 g* s; k4 o9 w! E' B: [- m- ~

+ O4 w- H7 z4 K( s$ w并编译,结果发现原始的公式是编译不过的,如下错误信息:  @/ J  C" T1 y1 X
  1. linking...( B' f: B8 r+ t( A' z% A- l4 g
  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.
    4 j0 ?4 N" b. a* O7 ]  @! ]* ^$ i
  3. Not enough information to list image symbols.( q( N! [- _  N  ^
  4. Finished: 1 information, 0 warning and 1 error messages.: d1 H% K% }6 N: @
  5. ".\STM320518_EVAL\STM320518_EVAL.axf" - 1 Error(s), 0 Warning(s).
    7 G5 O& h& a/ I3 @$ z/ o
  6. Target not created.
    0 H" J; T; M: b5 q" ^: \* v
  7. Build Time Elapsed:  00:00:08
复制代码
5 c4 Y4 j* ~/ ~8 h8 l' N2 ?, o
从字面上判断为编译system_stm32f0xx.c文件生成的目标文件system_stm32f0xx.o中的数据段(.data)内的RW数据与main.o中的数据在地址0x20000000产生冲突。
" E9 \* M" S, a% w仔细查看代码,发现main函数之前这么一段:# D1 _( V; P8 N+ c
  1. #if   (defined ( __CC_ARM ))* O! d" y( }8 I4 O4 _: ]! O7 B( J! u
  2.   __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));: d; u' v& w0 o. U" @) V
  3. #elif (defined (__ICCARM__))
    - _" {2 u# `; e) l: O/ h; S
  4. #pragma location = 0x20000000  {7 Q2 r. p8 z/ h8 N; r
  5.   __no_init __IO uint32_t VectorTable[48];
    1 n6 z7 V* C1 f! l, |$ L% |# H* W
  6. #elif defined   (  __GNUC__  )# V, J9 w2 y( n% v+ U& g* G% s
  7.   __IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));
    3 h4 ^/ ~( {8 {/ T
  8. #elif defined ( __TASKING__ )
    $ k2 u/ O0 ^+ Y& _, x- i7 Z. v0 x$ Y5 Z
  9.   __IO uint32_t VectorTable[48] __at(0x20000000);
    : E- f9 u% K2 z! z, R
  10. #endif
复制代码
$ P9 L' h+ F3 ], q1 y7 M
可见代码是要将中断向量表VectorTable强制定义在内存0x20000000上,但是此地址与system_stm32f0xx.c定义的全局变量位置有冲突。于是,需要修改避免冲突。中断向量的地址是固定的,但其他全局变量的地址可以相应地移动下,并且APP的烧录位置为0x8003000,如下图:
0 j' ^# A, `! f2 H  V4 k" r4 d: V  Q. _. x
20160728203625097.png

7 [1 T. g+ |* c  E+ ?! {( k( y
$ Q4 z* ~9 H6 V6 A再次编译,错误就会消失了。/ n; `6 m9 C+ ^% W# X4 }* j

2 q2 _7 g0 i. A( y另外需要将main函数内前面几行代码做些修改:
& Y/ {5 l+ P$ r9 {0 |4 ^
  1. int main(void)
    & ~2 r  ~: J5 L+ o& |- ^( ]
  2. {
    5 M6 s% b* r5 I% U' ]: _; S
  3.   uint32_t i = 0;/ R6 \4 L- C  g/ q/ [+ g8 P
  4. ' S8 f+ m( A" u& }. G8 b/ f( S$ S
  5.   /*!< At this stage the microcontroller clock setting is already configured, # D$ R) p+ T6 ~7 L  [
  6.        this is done through SystemInit() function which is called from startup
    ! M. g5 P% I  T
  7.        file (startup_stm32f0xx.s) before to branch to application main.
    $ q. @  X$ M9 n& e* v; b* Z+ g
  8.        To reconfigure the default setting of SystemInit() function, refer to
    1 U' j+ Z( X% r+ O6 y5 o
  9.        system_stm32f0xx.c file+ {0 g* J9 g5 F- o0 c
  10.      */
    / z) m6 v0 V! @& D$ o% p

  11. ; H: e0 x( E4 D, t& L' c
  12. /* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/  ; I& j% F7 X% T( M6 d

  13. ( V7 n# U& \) O
  14.   /* Copy the vector table from the Flash (mapped at the base of the application3 h( K: z1 C- G7 ^
  15.      load address 0x08003000) to the base address of the SRAM at 0x20000000. */8 M% `+ x) J1 z, W
  16.   for(i = 0; i < 48; i++)! H' U; G/ M% E) `( x* @! O
  17.   {$ Q5 J: f0 r. T1 I8 u- @
  18.     VectorTable<i> = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));
    ; U+ ]0 {5 U4 S8 U! [. S
  19.   </i>}3 {- {0 K; o1 }$ V

  20. 0 l/ @% c1 U! h& F; o
  21.   /* Enable the SYSCFG peripheral clock*/$ y; P6 B& z, `+ O+ }3 ]% g
  22.   //RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE); , ^9 Y( d, l( p* U* {
  23.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);    //需要修改成这样+ O& S0 d, C3 ?3 D# X4 a
  24.   /* Remap SRAM at 0x00000000 */1 |5 z* O: k% n; T
  25.   SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
    5 T1 L4 S, E" ?$ H
  26. - @$ v7 {( {# N; x, u, ]3 s' s
  27. /...
    1 B3 }& j$ p# T" s
  28. }
复制代码

3 x: _" N  m4 g打开对应的map文件,有如下内容:5 h" i- f1 c# z/ I: ?
  1. GPIO_PIN                                 0x08003470   Data           8  stm320518_eval.o(.constdata)& {4 [2 r3 W% u8 h- s
  2.     GPIO_CLK                                 0x08003478   Data          16  stm320518_eval.o(.constdata)% s7 x$ E; Z2 h" J
  3.     BUTTON_PIN                               0x08003488   Data          14  stm320518_eval.o(.constdata)+ @6 @6 [3 |2 {$ J" f/ U5 o% @! j
  4.     BUTTON_CLK                               0x08003498   Data          28  stm320518_eval.o(.constdata)+ L& f5 Y5 d  d0 X6 S0 N, A
  5.     BUTTON_EXTI_LINE                         0x080034b4   Data          14  stm320518_eval.o(.constdata)8 k! [# d( K3 A) K" @, V
  6.     BUTTON_PORT_SOURCE                       0x080034c2   Data          14  stm320518_eval.o(.constdata)
    % r) b, K  ?9 `! z1 X! ?1 N
  7.     BUTTON_PIN_SOURCE                        0x080034d0   Data          14  stm320518_eval.o(.constdata)
    ! R& X3 |# P) k$ P, V9 Y0 i9 p8 `
  8.     BUTTON_IRQn                              0x080034de   Data          14  stm320518_eval.o(.constdata)
    & X3 Z1 J5 s  q; P+ U' X
  9.     COM_USART_CLK                            0x080034ec   Data           4  stm320518_eval.o(.constdata)9 ?& W* V( Z& n+ ~. j
  10.     COM_TX_PORT_CLK                          0x080034f0   Data           4  stm320518_eval.o(.constdata)6 w5 T9 w! O) q" Z# G( k( g2 a" b
  11.     COM_RX_PORT_CLK                          0x080034f4   Data           4  stm320518_eval.o(.constdata)
    * {& d9 v* h+ Z/ I* c  A8 e" u
  12.     COM_TX_PIN                               0x080034f8   Data           2  stm320518_eval.o(.constdata)% [/ q  k& h) H2 O  [
  13.     COM_RX_PIN                               0x080034fa   Data           2  stm320518_eval.o(.constdata)
      \% A1 c9 o! s$ f6 ?, Q  ?; A. s
  14.     COM_TX_PIN_SOURCE                        0x080034fc   Data           2  stm320518_eval.o(.constdata)8 _- T0 j0 }7 n
  15.     COM_RX_PIN_SOURCE                        0x080034fe   Data           2  stm320518_eval.o(.constdata); |' X8 j" I% g
  16.     COM_TX_AF                                0x08003500   Data           2  stm320518_eval.o(.constdata)
    9 x$ J: @2 m  [8 j2 `
  17.     COM_RX_AF                                0x08003502   Data           2  stm320518_eval.o(.constdata)! a8 V  i0 G: [- R8 u+ N  j* C  L
  18.     Region$Table$Base                      0x08003504   Number         0  anon$obj.o(Region$Table)
    ) Q" f. R+ m* \. M( K  r  L  p% J
  19.     Region$Table$Limit                     0x08003524   Number         0  anon$obj.o(Region$Table). X" ~  u! l6 m* ~9 ~1 w
  20.     VectorTable                              0x20000000   Data         192  main.o(.ARM.__AT_0x20000000)      //向量表位置为0x20000000" x& M+ d% `& _8 X" r) H/ c& Y- u
  21.     SystemCoreClock                          0x200000c0   Data           4  system_stm32f0xx.o(.data)         //其他全局变量的起始位置为0x200000C0
    % ~7 e' P( `. p8 o1 S  |5 D, I
  22.     AHBPrescTable                            0x200000c4   Data          16  system_stm32f0xx.o(.data)
    . f: c, B5 [2 A8 i( j
  23.     GPIO_PORT                                0x200000d4   Data          16  stm320518_eval.o(.data)
    8 v/ l* ^; _0 I  q7 d# M
  24.     BUTTON_PORT                              0x200000e4   Data          28  stm320518_eval.o(.data): C) N7 N! ~5 i! c) |# g$ F
  25.     COM_USART                                0x20000100   Data           4  stm320518_eval.o(.data)' \; N2 r0 i  m3 j, v) ~, x
  26.     COM_TX_PORT                              0x20000104   Data           4  stm320518_eval.o(.data)
    ' L# d- ]- F8 @6 e& B- |' p
  27.     COM_RX_PORT                              0x20000108   Data           4  stm320518_eval.o(.data)
    4 l6 j" U4 \9 z* a
  28.     __initial_sp                             0x20000510   Data           0  startup_stm32f0xx.o(STACK)' Z( L. o0 ?9 o  |- ^& H- ?
复制代码
( W5 |  A- o9 t  @& l5 _0 S. e
如上所述,中断向量表被编译在0x20000000,内存的起始位置,而system_stm32f0xx.c下的全局变量SystemCoreClock被KEIL编译成放在紧挨着的0x200000C0的位置,与预期完全相符。分别将IAP与APP烧录进FLASH,测试可以正常运行。
% `/ f! e  k7 N$ M+ N
7 d. q3 n( I0 P* l注:在KEIL下,必须存在IAP才能调试APP!,这点是与IAR不同的。
6 S, u% w- ~8 N1 _0 ], D5 X5 X6 R( ?/ u8 A, V' \2 E' M

: Z6 u& r$ o9 O' T3 IAR下移植
" M" a. H6 A% F4 r# {在IAR下的IAP没有什么特殊的,主要还是看APP的配置。, Z( p8 H, E8 A/ q

# p9 d' H5 W! p, n8 j8 N5 `使用IAR打开APP工程,修改device为STM32F070:. I3 t3 _# b' s, v" e

. r' U. e0 |' E9 n$ ^
20160728213900343.png

6 l! m; {: H/ }/ \( u1 \0 ^8 B* n0 |9 }
4 Y6 t' C: o6 ]& o+ D" u/ J, t链接配置:
* \" Y; m, |" F
" ?0 ]! Q+ z; {5 G9 Y; T中断向量表:' m% h: Y! ~) K

3 A$ {6 ?  T2 r: O7 T3 l
20160728213954703.png
4 x. ?8 e* X3 I) m# T0 L( R& n
, w# L1 I- x. o% G" _
内存映射:$ i2 N. x: a6 \+ ]* r8 I. y9 M

: V) f8 v1 f# R2 g7 G
20160728214047079.png
! n2 \1 Q$ [& K9 ^( c) O
, S: y" ^/ v+ N8 f0 w# Q* T

. \7 k$ \, X  @2 q' n
4 k! ^* V+ c+ a* u* G# c; Y如上,APP存放在FLASH的位置0x8003000,内存还是设置为:0x20000000.( \7 k% |" d& b1 L5 o# O* w
5 f* S. [) D* n( K
编译后,打开对应的map文件如下所示:
9 G. ?$ p. H* _, w& y. v) d
) q' j, G- q4 O/ s8 `  V! b
  1. Entry                      Address  Size  Type      Object
    5 L) V4 V% b+ Y( v; I, ^
  2. -----                      -------  ----  ----      ------
    $ M0 Q& ^3 F# E' V4 D9 N4 e- g1 l
  3. .iar.init_table$Base   0x080034fc         --   Gb  - Linker created -
    ! T5 T7 c6 W+ F1 U1 s; D1 S, k
  4. .iar.init_table$Limit  0x08003510         --   Gb  - Linker created -
    * |3 T; F" b$ _: V
  5. ?main                   0x08003511        Code  Gb  cmain.o [4]3 _4 m2 h* J) f( `: M
  6. CSTACK$Base            0x200000d8         --   Gb  - Linker created -
    " u/ G' m. p! j+ P6 }4 V
  7. CSTACK$Limit           0x200010d8         --   Gb  - Linker created -) Z6 X6 Y2 Y; I! S1 H* m
  8. Delay                   0x080031e3  0x10  Code  Gb  main.o [1]; F; |; o$ Q$ |% ^4 q
  9. GPIO_PIN                0x080035a0   0x8  Data  Gb  stm320518_eval.o [1]% z) ~7 |6 y- o, M! r
  10. GPIO_PORT               0x200000c0  0x10  Data  Gb  stm320518_eval.o [1]           //stm320518_eval.c文件内的全局变量GPIO_PORT数组存放在0x200000c0
    2 u& O% v: |# U0 M8 t
  11. HardFault_Handler       0x08003573   0x4  Code  Gb  stm32f0xx_it.o [1]
      Q" ~+ Y) k3 `* N
  12. NMI_Handler             0x08003571   0x2  Code  Gb  stm32f0xx_it.o [1]1 J! h7 E! G: C
  13. NVIC_SetPriority        0x080030c1  0x84  Code  Lc  main.o [1]
    4 e2 O6 Z1 R; h- r% h) L
  14. PendSV_Handler          0x08003579   0x2  Code  Gb  stm32f0xx_it.o [1]
    4 F8 ]3 I; k% W9 F
  15. RCC_APB2PeriphClockCmd  0x08003229  0x20  Code  Gb  stm32f0xx_rcc.o [1]
    . y0 J1 K3 V) G4 B: ~
  16. Region$Table$Base     0x080034fc         --   Gb  - Linker created -
    1 A$ H: T1 Z" F/ m/ p. R+ Z& G
  17. Region$Table$Limit    0x08003510         --   Gb  - Linker created -
    , n- k4 P# Y- u6 p+ E/ d
  18. STM_EVAL_LEDToggle      0x08003315  0x26  Code  Gb  stm320518_eval.o [1]! M( I, n! g8 g0 z3 ^" X# U
  19. SVC_Handler             0x08003577   0x2  Code  Gb  stm32f0xx_it.o [1]6 i6 B1 A3 O  s4 _& U: S' V
  20. SYSCFG_MemoryRemapConfig
    / G; F# t8 A( f
  21.                         0x0800324d  0x14  Code  Gb  stm32f0xx_syscfg.o [1]
    9 G5 W7 s8 p. N. ~, a
  22. SetSysClock             0x080033b7  0xbe  Code  Lc  system_stm32f0xx.o [1]
      X! A5 }* f+ e! ~
  23. SysTick_Config          0x08003145  0x32  Code  Lc  main.o [1]
    8 M/ [( D; Q7 a4 Q
  24. SysTick_Handler         0x0800357b   0x8  Code  Gb  stm32f0xx_it.o [1]6 {% E3 Z, Z1 u5 V- k5 p/ a  `; s; q2 h
  25. SystemCoreClock         0x200000d0   0x4  Data  Gb  system_stm32f0xx.o [1]& I* D; n: K  M, \3 z& K
  26. SystemInit              0x08003349  0x6e  Code  Gb  system_stm32f0xx.o [1]1 g  P* G9 j( A, I5 _( W  B3 l7 y
  27. TimingDelay             0x200000d4   0x4  Data  Lc  main.o [1]
    & W/ T# V7 m$ Y6 B: Y
  28. TimingDelay_Decrement   0x080031f3  0x16  Code  Gb  main.o [1]
    6 i, Q, [+ r1 f3 K* K; j9 P4 f- q
  29. VectorTable             0x20000000  0xc0  Data  Gb  main.o [1]           //向量表编译位置为0x200000009 b' D4 @/ r2 J: |
  30. __aeabi_idiv0           0x08003345        Code  Gb  IntDivZer.o [4]
    ' d* K3 f( P+ f( D
  31. __aeabi_uidiv           0x08003265        Code  Gb  I32DivModFast.o [4]' T" ^2 @6 C" ~9 K- i
  32. __aeabi_uidivmod        0x08003265        Code  Gb  I32DivModFast.o [4]+ d* r: {) @% M- J
  33. __cmain                 0x08003511        Code  Gb  cmain.o [4]1 J* W- P, A4 x/ Q6 ~! k0 d( D1 e
  34. __exit                  0x08003545  0x14  Code  Gb  exit.o [5]
    % k; D. Z5 E$ L- D9 N. @$ Y
  35. __iar_copy_init3        0x080034a5  0x30  Code  Gb  copy_init3.o [4], a4 b. p- s9 X. L" y  k
  36. __iar_data_init3        0x080034d5  0x28  Code  Gb  data_init.o [4]
    % i5 Y- m3 C4 O' {6 i' n% \- T: \
  37. __iar_program_start     0x08003595        Code  Gb  cstartup_M.o [4]
    ' \, G  f4 L' l+ A# Y0 E; \
  38. __low_level_init        0x0800352b   0x4  Code  Gb  low_level_init.o [3]  t4 I5 |: N4 m6 @- Z6 h* o
  39. __vector_table          0x08003000        Data  Gb  startup_stm32f0xx.o [1], t, K! j8 [- J# ?, x1 F# x9 [1 y3 S
  40. _call_main              0x0800351d        Code  Gb  cmain.o [4]
    ! N3 k0 M* U7 x3 a) a( O' {
  41. _exit                   0x08003539        Code  Gb  cexit.o [4]. o) L, y% T2 X4 p$ P) v( F6 l
  42. _main                   0x08003527        Code  Gb  cmain.o [4]5 l+ U. T4 t8 B' \8 `. r: Q
  43. exit                    0x0800352f   0x8  Code  Gb  exit.o [3]# \+ r3 E% F. 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>
复制代码
( l/ O; A' T) i9 G0 J
如上所示,在IAR编译下,中断向量表被编译在0x20000000,内存的起始位置,而stm320518_eval.c下的全局变量GPIO_PORT被IAR编译成放在紧挨着的0x200000C0的位置。分别将IAP与APP烧录进FLASH,测试可以正常运行。
1 z; j+ Q- ~2 n3 P; R# y) W2 w0 \$ A4 ~! k9 o- Q, L
注:从IAR工程的链接配置来看,并没有像KEIL那样配置RAM位置为:0x2000000,编译后的结果向量表也不会与其他全局变量相冲突,可见IAR编译器已经自动计算并避免这种冲突,不像KEIL那样会出现链接错误,以此来提示用户。
& m4 o" k0 R9 ]6 s7 I! r
& H8 J2 h; ]- }: _3 g( Q另外:在IAR下,在不存在IAP的情况下也是可以调试APP的,这点是KEIL所不具备的功能,看样子,IAR在细节的处理上比KEIL要好。
5 m& a# B# h3 C( U, A% s/ J& j8 {& ^: T  Y$ p: `' M
1 G* Q1 T6 u! p+ S& f& Y
, U1 x, }. h- E8 M6 L
收藏 评论0 发布时间:2021-11-24 14:59

举报

0个回答

所属标签

相似技术帖

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