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

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

[复制链接]
STMCU小助手 发布时间:2021-11-24 14:59
1 前言% c- Q( s! D' A* S, ^
STSW-STM32116是ST官网基于标准库的针对STM32F0的USART进口IAP示例程序
0 C" Y9 j; |4 r' b8 R工程原本是针对STM32F051,本文将介绍如何移植到STM32F070,并针对移植的过程中的问题逐个处理。
7 O6 U* |" K) t1 }4 @+ V; k. o% ~3 E- k+ @3 V1 o( s# \" ^
2 KEIL下移植
! X4 m. R7 |% |% C& jIAP程序一般分为两个,一个是IAP,一个是APP,IAP存放在内置FLASH的0x8000000的起始位置,而APP则存放在离这个位置一定距离的位置,这个距离一定是大于或等于IAP本身所占空间大小,本例子为0x8003000。
) r" S# _" c8 a2 r& R, m. A' \: M" s, c( l; s
下载资源后,打开STM32F0xx_AN4065_FW_V1.0.0\Project\STM32F0xx_IAP\下的binary_template工程,这个就是APP工程,首先用KEIL打开,修改device为STM32F070,
' L! v, q6 X+ `
( K! }/ D4 N( ]. U, I; a' B
20160728204029911.png

0 @8 @3 Y- q' W: H0 i9 q  l- P+ _+ Q: W4 Q: ^
并编译,结果发现原始的公式是编译不过的,如下错误信息:$ w) V  d, \! i0 J# I
  1. linking...5 m" N; [' ?+ q6 q
  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.
    9 I/ U0 O; d3 ~" Q( q
  3. Not enough information to list image symbols.
    ( [2 p& ~  V) W- h2 ?5 C
  4. Finished: 1 information, 0 warning and 1 error messages.- _5 ^6 t, r* X# c; [8 G
  5. ".\STM320518_EVAL\STM320518_EVAL.axf" - 1 Error(s), 0 Warning(s).
    - w# w+ v" ]" Q0 z5 l
  6. Target not created.
    4 B# b/ L2 Z" G# A0 \0 l
  7. Build Time Elapsed:  00:00:08
复制代码
; E8 {( \$ a3 P+ A& g  P
从字面上判断为编译system_stm32f0xx.c文件生成的目标文件system_stm32f0xx.o中的数据段(.data)内的RW数据与main.o中的数据在地址0x20000000产生冲突。
! [5 R' k) w& ^仔细查看代码,发现main函数之前这么一段:
; B" H8 @$ ?# R5 N
  1. #if   (defined ( __CC_ARM ))
    ) f! T. Y7 k" \8 E2 P% A
  2.   __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));
    7 h9 H& v9 {. x0 l2 h2 C$ W7 B
  3. #elif (defined (__ICCARM__))
    & B( s* I/ J% l
  4. #pragma location = 0x200000008 T6 a2 z1 Z! h
  5.   __no_init __IO uint32_t VectorTable[48];
    8 {- W; @5 e  Y
  6. #elif defined   (  __GNUC__  )* n  H2 ]8 _' @7 B: U" k) L
  7.   __IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));
    0 m0 z7 Q, f) B# x5 _
  8. #elif defined ( __TASKING__ ); S4 w9 R; }& {" |( [, H' g
  9.   __IO uint32_t VectorTable[48] __at(0x20000000);
    0 a" j' v( u/ u, q3 k
  10. #endif
复制代码
/ P2 L6 K; e/ E1 E
可见代码是要将中断向量表VectorTable强制定义在内存0x20000000上,但是此地址与system_stm32f0xx.c定义的全局变量位置有冲突。于是,需要修改避免冲突。中断向量的地址是固定的,但其他全局变量的地址可以相应地移动下,并且APP的烧录位置为0x8003000,如下图:
& H- C5 m) N2 v; m
/ G/ u5 Z2 T" d. F3 e
20160728203625097.png

# Z& B- i9 s6 d$ H, }5 O  T, [# a! Q% p6 h
再次编译,错误就会消失了。
% h0 W# G* I$ |% [: n5 v7 H0 g
8 O; u' l/ I! K" D3 \另外需要将main函数内前面几行代码做些修改:* B/ ^' ]  v2 P! q
  1. int main(void)
    ! L0 r3 y" \9 ~) k
  2. {8 c1 o+ W1 B9 M
  3.   uint32_t i = 0;% i3 t' a$ U! U9 [

  4. + T: Q7 w1 e4 J
  5.   /*!< At this stage the microcontroller clock setting is already configured,
    * Z7 j; a- F7 d6 q
  6.        this is done through SystemInit() function which is called from startup9 a8 }1 @4 O" a1 z' Q7 C
  7.        file (startup_stm32f0xx.s) before to branch to application main.5 N+ c3 a$ U2 V% G
  8.        To reconfigure the default setting of SystemInit() function, refer to7 a  Y6 I# ~* h( e
  9.        system_stm32f0xx.c file
    ; W6 H1 B$ k9 {7 A9 i
  10.      */ % i8 W" q4 k# ?0 I" @6 p
  11. 8 R% P5 d) D+ z
  12. /* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/  
      O" [9 f# z0 e3 G

  13. ! n( m4 `# E  F' P" F0 E
  14.   /* Copy the vector table from the Flash (mapped at the base of the application, h5 p" A8 U4 u1 U! Y. Y
  15.      load address 0x08003000) to the base address of the SRAM at 0x20000000. *// L1 ]8 y) R: g7 ^6 h% r
  16.   for(i = 0; i < 48; i++)
    ' l, b$ t, ?2 M" b9 v+ e# @* x
  17.   {! O, O4 ], t( @  u4 V0 _
  18.     VectorTable<i> = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));$ z, i/ q. v, m7 S" @5 j2 [
  19.   </i>}
    0 R* g8 M+ t& g# x" x

  20. 2 e* o$ \- h6 i- X/ n# |
  21.   /* Enable the SYSCFG peripheral clock*/
    + [- q8 u& L2 w
  22.   //RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    7 l! B: S! h) ~: U8 `5 J8 Q
  23.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);    //需要修改成这样2 J9 I; B; h- [" C( d. s
  24.   /* Remap SRAM at 0x00000000 */' }/ u/ N% I' J* y' D) t1 W! M
  25.   SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);+ Q5 N' V% H( {  i, n

  26. % h5 F2 |+ p$ k0 [" M  \
  27. /...
    ; ^# y$ m8 i8 l  V5 r
  28. }
复制代码

" i2 v9 G& a( k; I) J' _打开对应的map文件,有如下内容:
8 }- [" d2 B2 i/ W- [
  1. GPIO_PIN                                 0x08003470   Data           8  stm320518_eval.o(.constdata): G# ^8 L2 e+ P5 ]2 F- |# V
  2.     GPIO_CLK                                 0x08003478   Data          16  stm320518_eval.o(.constdata)
    2 {5 ]! |, R1 U% r  G
  3.     BUTTON_PIN                               0x08003488   Data          14  stm320518_eval.o(.constdata)/ z' o' d6 G7 j7 K' A
  4.     BUTTON_CLK                               0x08003498   Data          28  stm320518_eval.o(.constdata)
    5 F% L, @; X# G# D' {8 A5 _1 I
  5.     BUTTON_EXTI_LINE                         0x080034b4   Data          14  stm320518_eval.o(.constdata)4 {) l5 |" W, M! x; T" x
  6.     BUTTON_PORT_SOURCE                       0x080034c2   Data          14  stm320518_eval.o(.constdata)
    ; I3 h: o! u0 ]; Z+ n9 t, v
  7.     BUTTON_PIN_SOURCE                        0x080034d0   Data          14  stm320518_eval.o(.constdata)
    8 g. X0 n. ?, h* H& e* q
  8.     BUTTON_IRQn                              0x080034de   Data          14  stm320518_eval.o(.constdata)
    3 }4 j. t6 a* m6 V5 _( J& @
  9.     COM_USART_CLK                            0x080034ec   Data           4  stm320518_eval.o(.constdata)
    ! {6 u6 o- j1 ]
  10.     COM_TX_PORT_CLK                          0x080034f0   Data           4  stm320518_eval.o(.constdata)
    ( M5 {9 \9 Y' B
  11.     COM_RX_PORT_CLK                          0x080034f4   Data           4  stm320518_eval.o(.constdata)* c5 h* M- C9 R) ]1 X
  12.     COM_TX_PIN                               0x080034f8   Data           2  stm320518_eval.o(.constdata)
    $ b$ |. W& [/ b2 ^3 {) o1 C
  13.     COM_RX_PIN                               0x080034fa   Data           2  stm320518_eval.o(.constdata)' d( e1 ?3 H; n/ X
  14.     COM_TX_PIN_SOURCE                        0x080034fc   Data           2  stm320518_eval.o(.constdata)3 }! ]6 v$ v5 ~: p9 R
  15.     COM_RX_PIN_SOURCE                        0x080034fe   Data           2  stm320518_eval.o(.constdata)$ d/ B  z3 V7 s. w. Q
  16.     COM_TX_AF                                0x08003500   Data           2  stm320518_eval.o(.constdata)+ ^% ]% y( Y( X, o2 K
  17.     COM_RX_AF                                0x08003502   Data           2  stm320518_eval.o(.constdata)6 ~  Y/ S: S7 Y
  18.     Region$Table$Base                      0x08003504   Number         0  anon$obj.o(Region$Table)9 S& T# T" e* z3 \1 }9 {
  19.     Region$Table$Limit                     0x08003524   Number         0  anon$obj.o(Region$Table)) g0 n" E. w: f" z+ P9 t
  20.     VectorTable                              0x20000000   Data         192  main.o(.ARM.__AT_0x20000000)      //向量表位置为0x200000000 H4 I# `8 a* F4 d
  21.     SystemCoreClock                          0x200000c0   Data           4  system_stm32f0xx.o(.data)         //其他全局变量的起始位置为0x200000C0
    5 s* C( A$ a7 M. @" C) E
  22.     AHBPrescTable                            0x200000c4   Data          16  system_stm32f0xx.o(.data)
    : t. m- l& S+ w7 B0 `0 f
  23.     GPIO_PORT                                0x200000d4   Data          16  stm320518_eval.o(.data). x9 F) [. p9 n: _) m8 e9 s
  24.     BUTTON_PORT                              0x200000e4   Data          28  stm320518_eval.o(.data)
    , ^/ @$ w2 n0 _: v" {1 m/ J
  25.     COM_USART                                0x20000100   Data           4  stm320518_eval.o(.data)
    , c5 Y) t1 H& S9 [% j- D
  26.     COM_TX_PORT                              0x20000104   Data           4  stm320518_eval.o(.data)3 w* C+ P# t2 m, q& Q/ m
  27.     COM_RX_PORT                              0x20000108   Data           4  stm320518_eval.o(.data)7 }+ F3 v* E1 g" u! C, s: x+ r
  28.     __initial_sp                             0x20000510   Data           0  startup_stm32f0xx.o(STACK); ~8 m0 d+ C0 i2 p" G3 n! J
复制代码

  U7 Z6 Y: I, ^. `7 T如上所述,中断向量表被编译在0x20000000,内存的起始位置,而system_stm32f0xx.c下的全局变量SystemCoreClock被KEIL编译成放在紧挨着的0x200000C0的位置,与预期完全相符。分别将IAP与APP烧录进FLASH,测试可以正常运行。
* o) _/ p' k+ s; H  u% f( e: a* D. P
注:在KEIL下,必须存在IAP才能调试APP!,这点是与IAR不同的。
5 Z4 f5 g2 `0 w# N- }3 }' \
" c$ E% p" Q! `. l* R  v1 P- u0 r2 S' z* E# V
3 IAR下移植
+ G, }6 h$ V  i5 Q) @% O* \在IAR下的IAP没有什么特殊的,主要还是看APP的配置。
$ {! U1 M3 p& U7 }3 I5 S
( Y, `( W  J2 x: c使用IAR打开APP工程,修改device为STM32F070:/ l; {( {0 v3 K: }

* A% A1 ]) ~, }$ ^9 s/ B3 k
20160728213900343.png
3 q0 S# ?- ]) o, y& A1 h: {

$ A8 z7 S& g$ M) j$ b链接配置:
/ z6 V# x9 A6 g; e1 Z1 q0 y2 B! c  O+ t
中断向量表:) \8 L1 W" r7 G4 p* l/ i( P0 A
1 X' s+ z7 C/ U" ~
20160728213954703.png
5 D, c5 d, ]8 k7 X
; o; [! R/ T. `: r" U4 H3 H' ^% p
内存映射:: y0 S0 h- Y& q2 ^+ Y* m! {5 U

6 B  v% Q' F4 a9 v3 O
20160728214047079.png

( U9 W4 ]: Y1 }: S( W1 s
- \1 T0 \. }1 W
1 Z, L4 x# \% Z4 j# j* l- o0 S
. _$ U  w3 Y8 o6 I9 B如上,APP存放在FLASH的位置0x8003000,内存还是设置为:0x20000000.. `8 ?0 m, @, T  S

3 ~  e) g7 C1 y6 X7 {: M4 g编译后,打开对应的map文件如下所示:) m- }- s8 ]; r9 \# J* K
3 w/ m- U1 x3 b/ q" |& Y) U
  1. Entry                      Address  Size  Type      Object
    ' c% ^! @, I7 v8 F  \) b: M/ m
  2. -----                      -------  ----  ----      ------
    ' b  T* j2 s3 K6 w9 ~
  3. .iar.init_table$Base   0x080034fc         --   Gb  - Linker created -& T4 v% }( G7 U9 B; R- `# r
  4. .iar.init_table$Limit  0x08003510         --   Gb  - Linker created -
    & p' G; ]  M$ ]  j. m# \
  5. ?main                   0x08003511        Code  Gb  cmain.o [4]$ W9 {7 ?- {8 H# q( `! Q8 m. Z
  6. CSTACK$Base            0x200000d8         --   Gb  - Linker created -2 K5 W; j5 k! H  }% V: ^7 ]7 s4 o
  7. CSTACK$Limit           0x200010d8         --   Gb  - Linker created -
    $ ]; |4 C+ J( y; |3 @
  8. Delay                   0x080031e3  0x10  Code  Gb  main.o [1]: e3 K' {! }& C0 Z. u$ d
  9. GPIO_PIN                0x080035a0   0x8  Data  Gb  stm320518_eval.o [1]
    ) @) I( [( x1 D9 D! v! G
  10. GPIO_PORT               0x200000c0  0x10  Data  Gb  stm320518_eval.o [1]           //stm320518_eval.c文件内的全局变量GPIO_PORT数组存放在0x200000c0
    ; k, q* H8 Q) O) w( r7 H6 [
  11. HardFault_Handler       0x08003573   0x4  Code  Gb  stm32f0xx_it.o [1]
    5 j2 Y  w# s0 t. v2 X- q4 l8 O
  12. NMI_Handler             0x08003571   0x2  Code  Gb  stm32f0xx_it.o [1]$ _5 X2 _1 S+ ]# }$ |" S
  13. NVIC_SetPriority        0x080030c1  0x84  Code  Lc  main.o [1]$ Q: j6 @" Y- O7 l; V
  14. PendSV_Handler          0x08003579   0x2  Code  Gb  stm32f0xx_it.o [1]
    , i# V- [% T8 ^% k  z( z( M
  15. RCC_APB2PeriphClockCmd  0x08003229  0x20  Code  Gb  stm32f0xx_rcc.o [1]
    5 O9 z- C5 U& ]
  16. Region$Table$Base     0x080034fc         --   Gb  - Linker created -
    ; Q+ b8 b2 H  w* w! w$ K& B
  17. Region$Table$Limit    0x08003510         --   Gb  - Linker created -4 D9 f) s5 L& D
  18. STM_EVAL_LEDToggle      0x08003315  0x26  Code  Gb  stm320518_eval.o [1]3 T$ U3 q( V  l
  19. SVC_Handler             0x08003577   0x2  Code  Gb  stm32f0xx_it.o [1]9 F4 e% i8 A: d1 d: Z
  20. SYSCFG_MemoryRemapConfig' {: C, [  w  w1 H- m  j
  21.                         0x0800324d  0x14  Code  Gb  stm32f0xx_syscfg.o [1]
    : {, c; j; f8 A3 R& k- E
  22. SetSysClock             0x080033b7  0xbe  Code  Lc  system_stm32f0xx.o [1]
    2 J0 M$ O, M- ^9 S! o8 A9 [
  23. SysTick_Config          0x08003145  0x32  Code  Lc  main.o [1]
    ; u; e- o5 e6 w) k
  24. SysTick_Handler         0x0800357b   0x8  Code  Gb  stm32f0xx_it.o [1]
    5 T& y1 L  J6 v0 E
  25. SystemCoreClock         0x200000d0   0x4  Data  Gb  system_stm32f0xx.o [1]
    " h* s2 z  P8 w- L; z% V
  26. SystemInit              0x08003349  0x6e  Code  Gb  system_stm32f0xx.o [1]* M% d: Q! ~: x
  27. TimingDelay             0x200000d4   0x4  Data  Lc  main.o [1]
    ' R1 R" c$ s. p4 H& w# V" h/ [* m
  28. TimingDelay_Decrement   0x080031f3  0x16  Code  Gb  main.o [1]
    ( L; I( m& i) i6 H6 J9 L, @
  29. VectorTable             0x20000000  0xc0  Data  Gb  main.o [1]           //向量表编译位置为0x20000000
    " L. I  {1 p( N% w1 |
  30. __aeabi_idiv0           0x08003345        Code  Gb  IntDivZer.o [4]
    ) l  o4 ~( M) X+ h; N4 q& R
  31. __aeabi_uidiv           0x08003265        Code  Gb  I32DivModFast.o [4]
    ; }) o+ k' n2 u) k5 Q7 f  a$ s
  32. __aeabi_uidivmod        0x08003265        Code  Gb  I32DivModFast.o [4]5 \' y+ S- q% _1 v4 M
  33. __cmain                 0x08003511        Code  Gb  cmain.o [4]
    7 e9 T8 {+ D$ e' S$ L
  34. __exit                  0x08003545  0x14  Code  Gb  exit.o [5]
    ( g0 |4 P5 S. ~' X1 i
  35. __iar_copy_init3        0x080034a5  0x30  Code  Gb  copy_init3.o [4]2 F6 T5 U9 _. m5 [& M
  36. __iar_data_init3        0x080034d5  0x28  Code  Gb  data_init.o [4]1 G% F* E% L" G  G6 V8 N7 V9 b1 G
  37. __iar_program_start     0x08003595        Code  Gb  cstartup_M.o [4]2 b2 a9 `& B0 I. Y8 n
  38. __low_level_init        0x0800352b   0x4  Code  Gb  low_level_init.o [3]
    ! o4 [0 c$ \% ~! [5 Z: t# ^1 R
  39. __vector_table          0x08003000        Data  Gb  startup_stm32f0xx.o [1]
    ) J0 k' Q; Q, f
  40. _call_main              0x0800351d        Code  Gb  cmain.o [4]) U5 A* ^" J+ z1 i( r) S
  41. _exit                   0x08003539        Code  Gb  cexit.o [4]1 D) k8 o* _2 K/ D% h! |
  42. _main                   0x08003527        Code  Gb  cmain.o [4]( j# `+ F$ U6 A9 D
  43. exit                    0x0800352f   0x8  Code  Gb  exit.o [3]$ c* c6 C5 H  d% @6 u1 |
  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>
复制代码
: b: G( U' V+ W5 \* b2 d- H9 u6 z
如上所示,在IAR编译下,中断向量表被编译在0x20000000,内存的起始位置,而stm320518_eval.c下的全局变量GPIO_PORT被IAR编译成放在紧挨着的0x200000C0的位置。分别将IAP与APP烧录进FLASH,测试可以正常运行。
5 x1 U' i0 W7 Q& ]; e; f# q) G' k
注:从IAR工程的链接配置来看,并没有像KEIL那样配置RAM位置为:0x2000000,编译后的结果向量表也不会与其他全局变量相冲突,可见IAR编译器已经自动计算并避免这种冲突,不像KEIL那样会出现链接错误,以此来提示用户。2 R1 q  \7 `4 g+ B+ f
  z1 O7 C; @$ e2 r1 u9 T
另外:在IAR下,在不存在IAP的情况下也是可以调试APP的,这点是KEIL所不具备的功能,看样子,IAR在细节的处理上比KEIL要好。3 U" R$ W5 s$ ^* I# P- l" E' }
, d8 @! p' I0 |# W4 I

, [- M. b0 I* r2 n
! {/ {# m" i& C, V5 r
收藏 评论0 发布时间:2021-11-24 14:59

举报

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