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

使用USART接口进行STM32F0的在线升级(AN4065)-基于标准库的STM32...

[复制链接]
aimejia 发布时间:2018-5-24 10:18
本帖最后由 aimejia 于 2018-5-24 10:25 编辑
2 V/ j: e- S- A3 R/ H' b6 l$ S- e) h* l0 ^. G
1 前言
& o4 A4 U' A' c. ~5 w1 P+ r( u; A- _. K       STSW-STM32116是ST官网基于标准库的针对STM32F0的USART进口IAP示例程序,下载链接:https://www.stmcu.org.cn/document/detail/index/id-213120
" i" D- i3 t1 S2 ~+ l6 {+ k; C& S       工程原本是针对STM32F051,本文将介绍如何移植到STM32F070,并针对移植的过程中的问题逐个处理。
4 b6 R9 H1 a3 ~8 @7 r. J- w1 M
2 KEIL下移植      
8 ?- B2 t/ D" Q: X
      IAP程序一般分为两个,一个是IAP,一个是APP,IAP存放在内置FLASH的0x8000000的起始位置,而APP则存放在离这个位置一定距离的位置,这个距离一定是大于或等于IAP本身所占空间大小,本例子为0x8003000。' V6 J0 o7 E* Y+ D

5 p9 ?# D  x% Z: ]      下载资源后,打开STM32F0xx_AN4065_FW_V1.0.0\Project\STM32F0xx_IAP\下的binary_template工程,这个就是APP工程,首先用KEIL打开,修改device为STM32F070,& u. @- I. Z) o7 e9 b

# ]1 }3 l5 P8 R% Z; Y
1.jpg

8 K3 X3 B6 c$ G: @0 t/ |; v# H4 W       并编译,结果发现原始的公式是编译不过的,如下错误信息:
; h3 U7 S! a) j
  1. <font face="Tahoma" size="2">[plain] view plain copy
    5 ^9 f% I- C0 N4 F- K0 I. _
  2. linking...  
    + f; j5 J/ B& \  }3 a2 ^* S  v
  3. .\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 ^4 D1 _' m( n5 W: O$ \7 ?
  4. Not enough information to list image symbols.  # c8 t; K- Q6 [* a
  5. Finished: 1 information, 0 warning and 1 error messages.  8 O% o6 c' ]' G' R+ C0 M/ N
  6. ".\STM320518_EVAL\STM320518_EVAL.axf" - 1 Error(s), 0 Warning(s).  9 ~/ v9 x8 p" H& m* D
  7. Target not created.  , ^3 O# e9 z" ~  L3 Q, t" S9 f
  8. Build Time Elapsed:  00:00:08  </font>
复制代码
      从字面上判断为编译system_stm32f0xx.c文件生成的目标文件system_stm32f0xx.o中的数据段(.data)内的RW数据与main.o中的数据在地址0x20000000产生冲突。9 M$ E1 I. g5 c. }
   
7 l8 l3 f0 _  F% @0 G3 y      仔细查看代码,发现main函数之前这么一段:
' y$ W/ Q& J1 f& V- a( l
  1. <font face="Tahoma" size="2">[cpp] view plain copy0 G/ W& c5 {* L6 Y
  2. #if   (defined ( __CC_ARM ))  6 [9 X' b: X# X5 S) j" [& ^6 @
  3.   __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));  5 l8 w* f: v; p9 Y1 f
  4. #elif (defined (__ICCARM__))  # e4 W! B. O  R. g5 C5 T1 v
  5. #pragma location = 0x20000000  
    * Y! Q; G. D8 z! [8 E
  6.   __no_init __IO uint32_t VectorTable[48];  ) z& b" z2 t3 g- s- o( V; g9 ?
  7. #elif defined   (  __GNUC__  )  2 v" M( w/ r1 ]* @# @2 z+ `' {( c3 @
  8.   __IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));  1 A0 {% |: x6 ~* A6 G
  9. #elif defined ( __TASKING__ )  & I3 O) e# \: i6 K( M4 |
  10.   __IO uint32_t VectorTable[48] __at(0x20000000);  ( r: r$ V8 N. I% g: o
  11. #endif  </font>
复制代码
      可见代码是要将中断向量表VectorTable强制定义在内存0x20000000上,但是此地址与system_stm32f0xx.c定义的全局变量位置有冲突。于是,需要修改避免冲突。中断向量的地址是固定的,但其他全局变量的地址可以相应地移动下,并且APP的烧录位置为0x8003000,如下图:8 u! D& y. N% z
# h7 X  C2 z7 m, A
2.jpg

- x% n! s$ e( w: V! W9 h$ t2 q  D       再次编译,错误就会消失了。; C$ y7 {1 z' D8 \: }9 T# A
  M. W: ~' B' q4 Q5 F! N' [  Z
       另外需要将main函数内前面几行代码做些修改:
% `# C- j- K3 _, v! S# @
  1. <font face="Tahoma" size="2">[cpp] view plain copy: R: k4 Z4 t# `0 \# j
  2. int main(void)  
    % z+ C# _) U# H6 i
  3. {  / v8 C! N( c$ l
  4.   uint32_t i = 0;  ( k' J- H1 ^# w1 |- ^: t
  5.   ( _6 U/ B$ C# H
  6.   /*!< At this stage the microcontroller clock setting is already configured,  * ^& }/ z5 r. Y6 S3 e" ^# L% a
  7.        this is done through SystemInit() function which is called from startup ( a# c6 ^: [8 m- l
  8.        file (startup_stm32f0xx.s) before to branch to application main. # [& q7 [2 u2 E% ~' Z
  9.        To reconfigure the default setting of SystemInit() function, refer to
    ( b1 s4 i3 }3 ~$ E* S5 |7 C
  10.        system_stm32f0xx.c file 1 v( `0 D) h7 M: G
  11.      */   + [% e3 Y! Z( i* X* {
  12.   
    - H3 p7 o7 S) k* ^
  13. /* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/   
    ' V5 [6 M$ p" i# d2 _4 y& q# M; j
  14.   / H4 f% Y1 Q& T( n
  15.   /* Copy the vector table from the Flash (mapped at the base of the application
    + k" O5 y8 g! q0 s2 P' S
  16.      load address 0x08003000) to the base address of the SRAM at 0x20000000. */  % @( Q% q" B2 ?$ p
  17.   for(i = 0; i < 48; i++)  
    " i$ R+ O6 Y: s3 {" d4 J
  18.   {  
    , G& T1 m) p' J6 p+ o
  19.     VectorTable[i] = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));  
    2 W% @, @* \7 e8 ^! a6 \- f; b" S
  20.   }  7 t) @; C. l' }; U. M3 d
  21.     U: j; n: {) M8 a6 y: S
  22.   /* Enable the SYSCFG peripheral clock*/  
    / v& R) N2 O$ F  {; W# x5 @
  23.   //RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);   
    . p$ k7 I" F# L0 d
  24.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);    //需要修改成这样  , W1 U8 i8 y5 r! j0 Z6 T
  25.   /* Remap SRAM at 0x00000000 */  
    $ V4 {0 E* G$ H; a3 T4 w# Z" n
  26.   SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);  
    & G* \: `8 r2 [$ a( C, R) w
  27.   
    ' i3 f9 x/ n, G$ i  R
  28. /...  1 s* i. V1 U3 w
  29. }  </font>
复制代码
      打开对应的map文件,有如下内容:4 |1 G' D4 f) K: l* z
  1. <font face="Tahoma" size="2">[plain] view plain copy3 @, {0 z( a& E( D
  2. GPIO_PIN                                 0x08003470   Data           8  stm320518_eval.o(.constdata)  
    / B" Z: ~% k" I
  3.    GPIO_CLK                                 0x08003478   Data          16  stm320518_eval.o(.constdata)  
    ; W7 H5 T3 }2 T
  4.    BUTTON_PIN                               0x08003488   Data          14  stm320518_eval.o(.constdata)  ( T5 x* P2 c. }- }2 m, _9 Y* w1 H
  5.    BUTTON_CLK                               0x08003498   Data          28  stm320518_eval.o(.constdata)  
    5 T$ `) F2 v% R' _3 g
  6.    BUTTON_EXTI_LINE                         0x080034b4   Data          14  stm320518_eval.o(.constdata)  6 t+ f+ t  y7 T& v$ W
  7.    BUTTON_PORT_SOURCE                       0x080034c2   Data          14  stm320518_eval.o(.constdata)  
    ) z! u; [( ?) o" y) b8 Y9 |' k
  8.    BUTTON_PIN_SOURCE                        0x080034d0   Data          14  stm320518_eval.o(.constdata)  4 i' ~& p8 x; ]( d0 K7 ^
  9.    BUTTON_IRQn                              0x080034de   Data          14  stm320518_eval.o(.constdata)  
    : o/ }% m& T% E3 |  t2 }7 X6 R
  10.    COM_USART_CLK                            0x080034ec   Data           4  stm320518_eval.o(.constdata)  
    $ M& U* d  v* f( q# l, C! \0 L* S
  11.    COM_TX_PORT_CLK                          0x080034f0   Data           4  stm320518_eval.o(.constdata)  
    % L6 K" q/ e; l! f$ L, f* \8 r
  12.    COM_RX_PORT_CLK                          0x080034f4   Data           4  stm320518_eval.o(.constdata)  . m% A, ~+ Q  j7 y. G9 I
  13.    COM_TX_PIN                               0x080034f8   Data           2  stm320518_eval.o(.constdata)  8 ~+ w5 o. E8 B) {+ Z$ Z) v. i
  14.    COM_RX_PIN                               0x080034fa   Data           2  stm320518_eval.o(.constdata)  % Y7 B, |( b, l+ `; M" {( Z
  15.    COM_TX_PIN_SOURCE                        0x080034fc   Data           2  stm320518_eval.o(.constdata)  # b4 T1 _" G  [3 s) V% ^: x: G
  16.    COM_RX_PIN_SOURCE                        0x080034fe   Data           2  stm320518_eval.o(.constdata)  ! V! [* ~8 ?) ?8 [8 e
  17.    COM_TX_AF                                0x08003500   Data           2  stm320518_eval.o(.constdata)  
    7 P1 \* e3 \* x' b0 r8 }
  18.    COM_RX_AF                                0x08003502   Data           2  stm320518_eval.o(.constdata)  
    $ I. l( b& p3 H8 ~! F  S
  19.    Region- c2 e: g- L- d0 z
  20. Table" ^! r( k% V; S: O& l. m' [( ]! ~
  21. Base                      0x08003504   Number         0  anon9 N! [% G: x+ S1 A4 T6 G& U
  22. obj.o(Region7 I6 z4 d% z* J; x* Q: F8 k5 ]
  23. Table)  7 c/ P& t$ ]' X' y; \0 M0 J. s
  24.    Region
    / A: S' b, R, x9 `
  25. Table/ E. I2 C* a. |" Q
  26. Limit                     0x08003524   Number         0  anon5 w, p( \1 C; j' c" v" d" W) L4 L3 f4 E
  27. obj.o(Region
    ! Z# c8 ?, w+ k& v. T6 G
  28. Table)  , n  A4 n% N( H0 d/ U/ K
  29.    VectorTable                              0x20000000   Data         192  main.o(.ARM.__AT_0x20000000)      //向量表位置为0x20000000  , p( N( C! q9 R  t3 G" t5 h0 ]+ L
  30.    SystemCoreClock                          0x200000c0   Data           4  system_stm32f0xx.o(.data)         //其他全局变量的起始位置为0x200000C0  
    % B  F$ [5 x% l0 I% y
  31.    AHBPrescTable                            0x200000c4   Data          16  system_stm32f0xx.o(.data)  
    " w# j7 z1 h; }! C
  32.    GPIO_PORT                                0x200000d4   Data          16  stm320518_eval.o(.data)  ( j( S* `$ p$ C( i. g
  33.    BUTTON_PORT                              0x200000e4   Data          28  stm320518_eval.o(.data)  : u) |0 G2 a  }9 i7 P/ a) z
  34.    COM_USART                                0x20000100   Data           4  stm320518_eval.o(.data)  
    - E5 u9 O" R0 q. S( t
  35.    COM_TX_PORT                              0x20000104   Data           4  stm320518_eval.o(.data)  
    . P$ A. Z7 l& e$ k9 c- _1 p9 s
  36.    COM_RX_PORT                              0x20000108   Data           4  stm320518_eval.o(.data)  
    2 Y0 A; c" H. D* t5 G
  37.    __initial_sp                             0x20000510   Data           0  startup_stm32f0xx.o(STACK)  </font>
复制代码
      如上所述,中断向量表被编译在0x20000000,内存的起始位置,而system_stm32f0xx.c下的全局变量SystemCoreClock被KEIL编译成放在紧挨着的0x200000C0的位置,与预期完全相符。分别将IAP与APP烧录进FLASH,测试可以正常运行。
) ~# o( r2 x8 y: ~1 b
; Y, n+ D6 M: g- p5 I6 c, S1 Y      注:在KEIL下,必须存在IAP才能调试APP!,这点是与IAR不同的。
; ~8 ^( l7 k; K
9 w# ]/ N1 r5 i9 d/ @3 IAR下移植
& P; G. s: ^, w, P     在IAR下的IAP没有什么特殊的,主要还是看APP的配置。' X2 i- H5 I1 n, }9 p0 A

6 q3 I6 s6 V7 Y; r4 _     使用IAR打开APP工程,修改device为STM32F070:9 q/ N. n5 [6 ]; J$ f4 V8 f

# F9 @) U6 V1 G$ O
3.jpg
, S$ k4 o' N5 d2 \
     链接配置:  h6 m% W+ _* U4 D% E) o  d
' w$ V& t* {9 W0 |% K0 d) A
     中断向量表:
. V4 e' S2 O3 {# @8 O+ G
2 c$ Y' f  ]# K% K8 @8 u; p) u
4.jpg
" q- I5 y0 e2 m
# K5 W! X% T* q1 I2 O  F+ F
     内存映射:
9 H) }. g2 h" @; h2 l; T2 T  e0 y$ C9 l
5.jpg

. ~+ K9 e9 B* {# |6 k) [$ _3 [       如上,APP存放在FLASH的位置0x8003000,内存还是设置为:0x20000000.
3 F9 [4 M. z1 a0 T3 o
0 l5 E" x/ Z7 L/ a7 s% @       编译后,打开对应的map文件如下所示:
; ]$ {. f! h1 \( m
  1. <font face="Tahoma" size="2">[plain] view plain copy
    . m+ @% H. k1 e
  2. Entry                      Address  Size  Type      Object  
    ( i5 g6 s( s1 }( f; p
  3. -----                      -------  ----  ----      ------  
    , O6 J. O- @! g. |3 u; _
  4. .iar.init_table$Base   0x080034fc         --   Gb  - Linker created -  
    * o! [# c! V# |: H/ i
  5. .iar.init_table$Limit  0x08003510         --   Gb  - Linker created -  ' r( r- a3 P9 H/ a, m/ |: f
  6. ?main                   0x08003511        Code  Gb  cmain.o [4]  1 q/ A% b1 T6 C# h+ r, x3 r
  7. CSTACK$Base            0x200000d8         --   Gb  - Linker created -  / G1 n; H2 Q  W* x
  8. CSTACK$Limit           0x200010d8         --   Gb  - Linker created -  * ~+ x8 s& @& J7 P8 V$ }0 _
  9. Delay                   0x080031e3  0x10  Code  Gb  main.o [1]  
    2 i9 ?. V+ i, r
  10. GPIO_PIN                0x080035a0   0x8  Data  Gb  stm320518_eval.o [1]  ( h) I" r6 x, U3 t3 E
  11. GPIO_PORT               0x200000c0  0x10  Data  Gb  stm320518_eval.o [1]           //stm320518_eval.c文件内的全局变量GPIO_PORT数组存放在0x200000c0  5 L" g+ b  G/ C* v
  12. HardFault_Handler       0x08003573   0x4  Code  Gb  stm32f0xx_it.o [1]  + M- h3 X1 W# d! ~$ N
  13. NMI_Handler             0x08003571   0x2  Code  Gb  stm32f0xx_it.o [1]  
    ; ?- j+ d7 \) Y- O! F
  14. NVIC_SetPriority        0x080030c1  0x84  Code  Lc  main.o [1]  
    * w% W. n3 Z( c
  15. PendSV_Handler          0x08003579   0x2  Code  Gb  stm32f0xx_it.o [1]  ) D$ m. H/ Q- b7 c/ D6 X( D
  16. RCC_APB2PeriphClockCmd  0x08003229  0x20  Code  Gb  stm32f0xx_rcc.o [1]    l7 R4 Z2 V8 s" @  E- i( k2 p& G
  17. Region
    0 i/ J; B; G$ U! }& I0 V
  18. Table
    ) Y/ \$ d7 m" V8 e& j; P4 e# t
  19. Base     0x080034fc         --   Gb  - Linker created -  
    # l% W6 G  t3 {
  20. Region& A. z: e% |8 n, A& E& O
  21. Table
    8 L" \1 L( ~4 w9 v. \1 O' s4 W1 S9 _
  22. Limit    0x08003510         --   Gb  - Linker created -  ; g( t2 k6 O  t1 O# @- V
  23. STM_EVAL_LEDToggle      0x08003315  0x26  Code  Gb  stm320518_eval.o [1]  
      l: c4 B% v5 }4 V; w+ u
  24. SVC_Handler             0x08003577   0x2  Code  Gb  stm32f0xx_it.o [1]  
    & {* q7 \, ~# G7 ?
  25. SYSCFG_MemoryRemapConfig  & u+ w3 c1 p# v/ Z1 g  r  A5 U
  26.                         0x0800324d  0x14  Code  Gb  stm32f0xx_syscfg.o [1]  4 Y! u. t. F2 w  R
  27. SetSysClock             0x080033b7  0xbe  Code  Lc  system_stm32f0xx.o [1]  5 x) O+ T* [* }5 W! ]& {) l
  28. SysTick_Config          0x08003145  0x32  Code  Lc  main.o [1]  
    * k  D# B$ [! B. k2 [' _' Y9 {! j
  29. SysTick_Handler         0x0800357b   0x8  Code  Gb  stm32f0xx_it.o [1]  ! ]" v; z+ l3 w$ o: L- q
  30. SystemCoreClock         0x200000d0   0x4  Data  Gb  system_stm32f0xx.o [1]  
    % S/ {1 L+ B+ y3 r" A& O
  31. SystemInit              0x08003349  0x6e  Code  Gb  system_stm32f0xx.o [1]  
    * M) a( _3 j/ W8 l# f7 n
  32. TimingDelay             0x200000d4   0x4  Data  Lc  main.o [1]  . }$ O5 X4 k+ l2 g$ u
  33. TimingDelay_Decrement   0x080031f3  0x16  Code  Gb  main.o [1]  . s0 s  s! {( [
  34. VectorTable             0x20000000  0xc0  Data  Gb  main.o [1]           //向量表编译位置为0x20000000  7 h1 E, Q" l3 {, d' D
  35. __aeabi_idiv0           0x08003345        Code  Gb  IntDivZer.o [4]  2 g2 ?6 X  A0 j% J5 J
  36. __aeabi_uidiv           0x08003265        Code  Gb  I32DivModFast.o [4]  
    / {, o  P% z% _
  37. __aeabi_uidivmod        0x08003265        Code  Gb  I32DivModFast.o [4]  
    ; `4 t, s& t, p, o* f" k
  38. __cmain                 0x08003511        Code  Gb  cmain.o [4]  
    % j& [; o$ w8 |( g
  39. __exit                  0x08003545  0x14  Code  Gb  exit.o [5]  ) `, E6 ]3 N" |5 R2 S  _! b. u
  40. __iar_copy_init3        0x080034a5  0x30  Code  Gb  copy_init3.o [4]  
    " f  M% a8 q0 T
  41. __iar_data_init3        0x080034d5  0x28  Code  Gb  data_init.o [4]  : R% }: o2 ?0 w: C" k: X' {: ?
  42. __iar_program_start     0x08003595        Code  Gb  cstartup_M.o [4]  3 g8 L- P* r$ k
  43. __low_level_init        0x0800352b   0x4  Code  Gb  low_level_init.o [3]  
    $ Y8 G, l  A, G$ E. f
  44. __vector_table          0x08003000        Data  Gb  startup_stm32f0xx.o [1]  + r7 z. D! X4 g# M. _  p/ e; I2 Z
  45. _call_main              0x0800351d        Code  Gb  cmain.o [4]  
    ( `2 I6 E# \6 Y: y
  46. _exit                   0x08003539        Code  Gb  cexit.o [4]  
    5 r2 s6 S2 S2 H  H! F' I* K2 R
  47. _main                   0x08003527        Code  Gb  cmain.o [4]  ( C' m* ^+ ~  `
  48. exit                    0x0800352f   0x8  Code  Gb  exit.o [3]  4 [. o; y& z5 @' l  r3 o8 o& q
  49. main                    0x08003177  0x6c  Code  Gb  main.o [1]  </font>
复制代码
       如上所示,在IAR编译下,中断向量表被编译在0x20000000,内存的起始位置,而stm320518_eval.c下的全局变量GPIO_PORT被IAR编译成放在紧挨着的0x200000C0的位置。分别将IAP与APP烧录进FLASH,测试可以正常运行。
" g. D5 G7 i  g* U0 s1 t3 ?, E/ l, q& Q" H
       注:从IAR工程的链接配置来看,并没有像KEIL那样配置RAM位置为:0x2000000,编译后的结果向量表也不会与其他全局变量相冲突,可见IAR编译器已经自动计算并避免这种冲突,不像KEIL那样会出现链接错误,以此来提示用户。+ Z: ~4 b0 P; s" d6 d; Y
9 g: S1 q. o1 \9 V
       另外:在IAR下,在不存在IAP的情况下也是可以调试APP的,这点是KEIL所不具备的功能,看样子,IAR在细节的处理上比KEIL要好。
" R) H+ B# q" Y8 i" `1 p1 ^2 s3 h
7 N! B) M2 a0 l5 a9 S) _" G# Q7 Q
转载自FD6 b5 C9 I& b. R: \5 x; w

# h7 I4 Q+ Q, {5 u' [- f3 z6 d+ t
赞 收藏 2 评论0 发布时间:2018-5-24 10:18

举报

0个回答

所属标签

相似技术帖

官网相关资源

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