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

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

[复制链接]
STMCU小助手 发布时间:2021-11-24 14:59
1 前言+ H$ H: c5 i: R
STSW-STM32116是ST官网基于标准库的针对STM32F0的USART进口IAP示例程序
0 e  I" J( O+ ]; @4 ?, ]工程原本是针对STM32F051,本文将介绍如何移植到STM32F070,并针对移植的过程中的问题逐个处理。/ a3 E: v% o$ P6 z3 Q
* Z7 V* e' f' I
2 KEIL下移植; s$ N' @, H) I
IAP程序一般分为两个,一个是IAP,一个是APP,IAP存放在内置FLASH的0x8000000的起始位置,而APP则存放在离这个位置一定距离的位置,这个距离一定是大于或等于IAP本身所占空间大小,本例子为0x8003000。
5 m; J- ?4 K+ P4 g- F, [
3 A$ l9 U$ [0 L1 ^6 d下载资源后,打开STM32F0xx_AN4065_FW_V1.0.0\Project\STM32F0xx_IAP\下的binary_template工程,这个就是APP工程,首先用KEIL打开,修改device为STM32F070,8 k/ A/ V: R7 j: S9 t

, i, D+ y( v2 j  S  d5 ^; `
20160728204029911.png
; a7 w9 k7 U  a1 _

3 {' R; H% Y0 p! g& b4 s, \4 E并编译,结果发现原始的公式是编译不过的,如下错误信息:
9 K' R6 F- `  w* h; m' ^
  1. linking...3 f: t+ p- j) f, Y0 w
  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.
    8 G8 |( ]4 b8 G# N  j7 c+ q7 I
  3. Not enough information to list image symbols.
    ; K# [+ ^. ]+ k7 ]* x
  4. Finished: 1 information, 0 warning and 1 error messages.
    ( T2 M+ Q3 b$ {" G$ m+ G
  5. ".\STM320518_EVAL\STM320518_EVAL.axf" - 1 Error(s), 0 Warning(s).* ]6 W+ d6 j# D% m) ^% ~
  6. Target not created." {8 e, v2 w( G( w  l! k) d( N5 S
  7. Build Time Elapsed:  00:00:08
复制代码
/ z, d3 |3 X  G8 k% I* x5 N
从字面上判断为编译system_stm32f0xx.c文件生成的目标文件system_stm32f0xx.o中的数据段(.data)内的RW数据与main.o中的数据在地址0x20000000产生冲突。
5 h" F* @2 s2 Q仔细查看代码,发现main函数之前这么一段:
; x" d6 V; ]& J" y& z
  1. #if   (defined ( __CC_ARM ))
    , R) D# a! n  M
  2.   __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));
    / e) G% b1 @+ [  w: B0 c
  3. #elif (defined (__ICCARM__))
    # d5 K0 }# \$ ~3 N
  4. #pragma location = 0x20000000* A8 [5 Q) ?2 H9 `
  5.   __no_init __IO uint32_t VectorTable[48];
    : _: _* z  X7 F1 b0 }" u
  6. #elif defined   (  __GNUC__  )
    ; Y: k6 W' j4 O9 j8 _7 T: s
  7.   __IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));
    1 E+ ^# c7 c# v* ~! Y
  8. #elif defined ( __TASKING__ )
    $ B) z' S" q- Z/ [
  9.   __IO uint32_t VectorTable[48] __at(0x20000000);
    . t) Q' i; K/ |& U! ~4 z: X
  10. #endif
复制代码
9 [" ~* }. ]& y2 m$ i9 t
可见代码是要将中断向量表VectorTable强制定义在内存0x20000000上,但是此地址与system_stm32f0xx.c定义的全局变量位置有冲突。于是,需要修改避免冲突。中断向量的地址是固定的,但其他全局变量的地址可以相应地移动下,并且APP的烧录位置为0x8003000,如下图:
4 Z: _/ M. C4 S5 _# A( f4 ?( U; ~* I1 d* V% F6 j3 d9 ]& o
20160728203625097.png
6 }: x& B4 J; z, @
. ~3 P! e* p/ I% ~
再次编译,错误就会消失了。4 V8 R, s7 V  {. V  p/ F* Q

7 _! m( ]8 ~: _9 y6 u另外需要将main函数内前面几行代码做些修改:, f: J2 _, Q+ a( Y" R  A' Z) F' M% n
  1. int main(void)& R- h; w! p8 L  L, q
  2. {
    2 V  e& p: m1 \0 Y1 \
  3.   uint32_t i = 0;1 h& f) p, F6 G
  4. ! g$ r! c+ w! y7 N5 ~
  5.   /*!< At this stage the microcontroller clock setting is already configured,
    0 ^1 S5 l5 \, n% V# V
  6.        this is done through SystemInit() function which is called from startup
    % v. b# A8 X. }5 f+ t( o
  7.        file (startup_stm32f0xx.s) before to branch to application main.# y. B, e) |, R+ x$ v
  8.        To reconfigure the default setting of SystemInit() function, refer to
      |" @, g3 i! ?  a
  9.        system_stm32f0xx.c file3 ^: Q3 V' V! ^' ]( c2 y
  10.      */
    + U7 }- v# n  l) g" v) \3 b4 y
  11. $ `8 N, g: k# _5 d# T3 i
  12. /* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/  & D% s# z+ t* U1 G) M7 i
  13. 6 z9 E0 |% Q8 }: j
  14.   /* Copy the vector table from the Flash (mapped at the base of the application6 R9 Z+ Q3 N) Z8 j0 |) d
  15.      load address 0x08003000) to the base address of the SRAM at 0x20000000. */% w8 F" y7 O* D1 N" D
  16.   for(i = 0; i < 48; i++)' _! H; X. D( K" ]* S1 u
  17.   {
    # n9 D; G4 _) M2 `. }* f
  18.     VectorTable<i> = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));
    # o, ~5 k7 \; k
  19.   </i>}! b) Y3 Q: o2 c  Y4 ^3 `! z
  20. % }$ T+ X2 k7 \0 q; a4 y% I  u2 E! I
  21.   /* Enable the SYSCFG peripheral clock*/$ Q6 I. }/ @. r! F; e3 j
  22.   //RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    , B" i" D. g5 J
  23.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);    //需要修改成这样
    ( R2 ~; N$ ~* C* r4 `8 J
  24.   /* Remap SRAM at 0x00000000 */) c: S* Q1 c2 T1 w$ B
  25.   SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);$ t/ h9 A3 o! x
  26. 7 a  `; I' c" v0 @9 O! G  \
  27. /...
    4 @; [( d5 v6 Q) q# b0 k- V) p  P
  28. }
复制代码

- \1 ^& X' e- T. l打开对应的map文件,有如下内容:
- F5 Z8 L! Q7 i% u, c1 [4 ?
  1. GPIO_PIN                                 0x08003470   Data           8  stm320518_eval.o(.constdata)' u7 G' I. O4 r/ f) [( Q
  2.     GPIO_CLK                                 0x08003478   Data          16  stm320518_eval.o(.constdata)
    " j$ {+ c7 N) h0 O" D: }
  3.     BUTTON_PIN                               0x08003488   Data          14  stm320518_eval.o(.constdata)
    8 f  F, X+ K9 A
  4.     BUTTON_CLK                               0x08003498   Data          28  stm320518_eval.o(.constdata)( a6 W0 h' H' t
  5.     BUTTON_EXTI_LINE                         0x080034b4   Data          14  stm320518_eval.o(.constdata)3 N8 R" R. l3 [7 V; c
  6.     BUTTON_PORT_SOURCE                       0x080034c2   Data          14  stm320518_eval.o(.constdata)
    & V1 K1 Z9 K. T9 i
  7.     BUTTON_PIN_SOURCE                        0x080034d0   Data          14  stm320518_eval.o(.constdata)
    9 h  u3 k) ^5 Q$ M7 u) E
  8.     BUTTON_IRQn                              0x080034de   Data          14  stm320518_eval.o(.constdata)4 W* \+ k4 y" |- h
  9.     COM_USART_CLK                            0x080034ec   Data           4  stm320518_eval.o(.constdata)6 T: M6 n" u0 j
  10.     COM_TX_PORT_CLK                          0x080034f0   Data           4  stm320518_eval.o(.constdata)
    " ]- S% g* M' k* \  o- u
  11.     COM_RX_PORT_CLK                          0x080034f4   Data           4  stm320518_eval.o(.constdata)
    . W" f* b: @1 Q
  12.     COM_TX_PIN                               0x080034f8   Data           2  stm320518_eval.o(.constdata)+ {& c/ }7 k( v5 w/ f. X  ?
  13.     COM_RX_PIN                               0x080034fa   Data           2  stm320518_eval.o(.constdata)
    7 k9 q3 t8 i* q+ D
  14.     COM_TX_PIN_SOURCE                        0x080034fc   Data           2  stm320518_eval.o(.constdata)
    # n# U& z; B. K# x' H+ t
  15.     COM_RX_PIN_SOURCE                        0x080034fe   Data           2  stm320518_eval.o(.constdata)
    8 N" i; g/ P) ]) }
  16.     COM_TX_AF                                0x08003500   Data           2  stm320518_eval.o(.constdata)
    7 ]  i$ D/ {, G0 R3 J
  17.     COM_RX_AF                                0x08003502   Data           2  stm320518_eval.o(.constdata)
    5 l( C: n6 b1 P# ~2 `; Y
  18.     Region$Table$Base                      0x08003504   Number         0  anon$obj.o(Region$Table)
    # w' K& D4 t4 D
  19.     Region$Table$Limit                     0x08003524   Number         0  anon$obj.o(Region$Table)+ A: G9 y0 o( T" j8 b- F, {( L
  20.     VectorTable                              0x20000000   Data         192  main.o(.ARM.__AT_0x20000000)      //向量表位置为0x20000000
    # g; F$ i0 L& G: n# l
  21.     SystemCoreClock                          0x200000c0   Data           4  system_stm32f0xx.o(.data)         //其他全局变量的起始位置为0x200000C09 ]/ n/ F: w& p" {
  22.     AHBPrescTable                            0x200000c4   Data          16  system_stm32f0xx.o(.data)* c" _4 J5 x& \' P0 s: s
  23.     GPIO_PORT                                0x200000d4   Data          16  stm320518_eval.o(.data)! h+ p) y! d7 c5 L4 h7 M
  24.     BUTTON_PORT                              0x200000e4   Data          28  stm320518_eval.o(.data)
    + U! {6 H6 [/ x. {1 k( p( J
  25.     COM_USART                                0x20000100   Data           4  stm320518_eval.o(.data)
    % @$ o1 u# L$ b1 L) Y$ g3 I1 p/ ]
  26.     COM_TX_PORT                              0x20000104   Data           4  stm320518_eval.o(.data)+ b1 G/ `' L0 e9 m
  27.     COM_RX_PORT                              0x20000108   Data           4  stm320518_eval.o(.data)
    . m. u7 W# n* ?; B
  28.     __initial_sp                             0x20000510   Data           0  startup_stm32f0xx.o(STACK). @2 Z  `% X% _4 ?4 Y2 x
复制代码
! |; u9 O3 O7 l' f" @
如上所述,中断向量表被编译在0x20000000,内存的起始位置,而system_stm32f0xx.c下的全局变量SystemCoreClock被KEIL编译成放在紧挨着的0x200000C0的位置,与预期完全相符。分别将IAP与APP烧录进FLASH,测试可以正常运行。& {- E+ F  J. }
/ |6 @6 c2 S0 W  U
注:在KEIL下,必须存在IAP才能调试APP!,这点是与IAR不同的。4 `3 K8 E8 a4 v, w: R0 j
% x4 Z' l+ E( s: B; b" E
, l! `# m/ w' s  d( ?+ h
3 IAR下移植% [* d6 @7 Q% P. q  o3 X* M: U
在IAR下的IAP没有什么特殊的,主要还是看APP的配置。9 z" r3 d+ e  m9 B/ A6 q

) d; u7 O+ I% ~6 `- R3 D8 Y使用IAR打开APP工程,修改device为STM32F070:
* l  F- [& R( F1 |' y' X( L& o; L  m* h# Y2 {1 t
20160728213900343.png
/ T( i2 ~$ l  _5 p. V  O+ f
8 M: M& q. Z5 E* S4 S! X7 R
链接配置:" r( i3 G8 h$ [6 ^* B
# I5 [) i( j8 N) R
中断向量表:+ j* S* F3 U. A2 E8 q' o: F
( a  g$ f# g& d6 m
20160728213954703.png
! _* s) Q3 [( M8 o
1 p) ?6 |9 h# `9 `1 s  o
内存映射:& f8 K% t1 d! c/ c3 e# o# |; Z; ~' e
7 e/ U9 h0 X, X+ S4 @
20160728214047079.png

' Y  t0 P; @! ^4 }& x% S# _
/ i9 h1 o, P  P+ z6 ^4 o
: o+ p8 g$ f' l0 V2 ~4 @0 S$ S  ^6 v: ]+ J' {9 @
如上,APP存放在FLASH的位置0x8003000,内存还是设置为:0x20000000.  A3 t* r/ B& e* g

& W" _, i+ n+ z( x7 g1 D, h' q7 J编译后,打开对应的map文件如下所示:
1 z* S8 o/ a, D9 F! s2 }+ S+ T8 l2 _
  1. Entry                      Address  Size  Type      Object- \! s% w! d0 \5 ]7 Z1 H
  2. -----                      -------  ----  ----      ------; |; J/ N! J8 H
  3. .iar.init_table$Base   0x080034fc         --   Gb  - Linker created -
    * o  ^( W% g' f- l. L5 N( F
  4. .iar.init_table$Limit  0x08003510         --   Gb  - Linker created -2 T; d" U  K! j# x
  5. ?main                   0x08003511        Code  Gb  cmain.o [4]) M4 o7 f7 ~1 m9 D8 _
  6. CSTACK$Base            0x200000d8         --   Gb  - Linker created -" [! X% I' [6 J% [' J
  7. CSTACK$Limit           0x200010d8         --   Gb  - Linker created -0 L; o7 V, B. A1 n9 `3 r* _( w7 C9 ?
  8. Delay                   0x080031e3  0x10  Code  Gb  main.o [1]8 M' A: Z# [' ]3 x. C' U7 u9 G; V
  9. GPIO_PIN                0x080035a0   0x8  Data  Gb  stm320518_eval.o [1]( Y1 {9 i4 t/ e3 t5 O. x1 z) ]: l2 q
  10. GPIO_PORT               0x200000c0  0x10  Data  Gb  stm320518_eval.o [1]           //stm320518_eval.c文件内的全局变量GPIO_PORT数组存放在0x200000c0/ V. y' X0 }' C1 t. u
  11. HardFault_Handler       0x08003573   0x4  Code  Gb  stm32f0xx_it.o [1]
    $ I4 Q: z6 ]+ \! k$ G) S& ~' V' {& K" c
  12. NMI_Handler             0x08003571   0x2  Code  Gb  stm32f0xx_it.o [1]
    * a0 `2 U% `! r1 q- ~7 \- F" V
  13. NVIC_SetPriority        0x080030c1  0x84  Code  Lc  main.o [1]4 u7 v+ J, G% z6 m
  14. PendSV_Handler          0x08003579   0x2  Code  Gb  stm32f0xx_it.o [1]4 `6 ~4 H9 y9 Q5 d6 O
  15. RCC_APB2PeriphClockCmd  0x08003229  0x20  Code  Gb  stm32f0xx_rcc.o [1]
    ' q3 k& n1 e& Z
  16. Region$Table$Base     0x080034fc         --   Gb  - Linker created -
    + |3 S6 L1 A* ?( N) W6 b
  17. Region$Table$Limit    0x08003510         --   Gb  - Linker created -8 a: N1 n0 C4 ^4 w
  18. STM_EVAL_LEDToggle      0x08003315  0x26  Code  Gb  stm320518_eval.o [1]% G9 i0 f& }. h) p9 L6 H) ]
  19. SVC_Handler             0x08003577   0x2  Code  Gb  stm32f0xx_it.o [1]0 W( u, i/ I7 V+ X
  20. SYSCFG_MemoryRemapConfig7 j7 ]  b- x: ]- \
  21.                         0x0800324d  0x14  Code  Gb  stm32f0xx_syscfg.o [1]) D: m9 b8 n  \+ v
  22. SetSysClock             0x080033b7  0xbe  Code  Lc  system_stm32f0xx.o [1]/ Z/ J$ P4 `! V/ ~
  23. SysTick_Config          0x08003145  0x32  Code  Lc  main.o [1]8 l& n2 P: x, J# O& ]7 G
  24. SysTick_Handler         0x0800357b   0x8  Code  Gb  stm32f0xx_it.o [1]
    $ C  Z+ c- T3 @& h
  25. SystemCoreClock         0x200000d0   0x4  Data  Gb  system_stm32f0xx.o [1]' J: \( o5 x% R
  26. SystemInit              0x08003349  0x6e  Code  Gb  system_stm32f0xx.o [1]) `% ^2 `; Z- }# P$ n6 R
  27. TimingDelay             0x200000d4   0x4  Data  Lc  main.o [1]
    4 G5 i& A8 Z8 y4 p( j
  28. TimingDelay_Decrement   0x080031f3  0x16  Code  Gb  main.o [1]
    4 n/ \- Y( ]" ~" |8 q' V+ _6 U
  29. VectorTable             0x20000000  0xc0  Data  Gb  main.o [1]           //向量表编译位置为0x20000000* q, Y. \9 [+ B9 U9 \
  30. __aeabi_idiv0           0x08003345        Code  Gb  IntDivZer.o [4]
    % C. N7 D1 i) O  }; j
  31. __aeabi_uidiv           0x08003265        Code  Gb  I32DivModFast.o [4]: Y, }" x( Q# U  L3 w
  32. __aeabi_uidivmod        0x08003265        Code  Gb  I32DivModFast.o [4], ]0 L; ]  \; ~! A
  33. __cmain                 0x08003511        Code  Gb  cmain.o [4]1 H& E/ M, g' {8 n( _" ]
  34. __exit                  0x08003545  0x14  Code  Gb  exit.o [5]
    1 H8 n$ N# A- b
  35. __iar_copy_init3        0x080034a5  0x30  Code  Gb  copy_init3.o [4]
    $ d5 `; y' A2 a* Z' h  L) P4 u
  36. __iar_data_init3        0x080034d5  0x28  Code  Gb  data_init.o [4]
    3 l- L1 X) }9 y, Z9 R! @$ Y& r
  37. __iar_program_start     0x08003595        Code  Gb  cstartup_M.o [4]/ B0 J: @; V1 r& E
  38. __low_level_init        0x0800352b   0x4  Code  Gb  low_level_init.o [3]
    & w  r' ~; s. Z
  39. __vector_table          0x08003000        Data  Gb  startup_stm32f0xx.o [1]
    . x0 C$ {' q) e- w: ]# m
  40. _call_main              0x0800351d        Code  Gb  cmain.o [4]
    $ Q! V' Z, m3 x. @8 p  R; T
  41. _exit                   0x08003539        Code  Gb  cexit.o [4]' s8 R: F0 Y& G- v" v8 _( Q* e, m
  42. _main                   0x08003527        Code  Gb  cmain.o [4]
    2 [- p& W$ J0 s) W; Y
  43. exit                    0x0800352f   0x8  Code  Gb  exit.o [3]
    % [! |6 p/ }+ _. M
  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>
复制代码
: Y' ]" F- ]% N; {6 B
如上所示,在IAR编译下,中断向量表被编译在0x20000000,内存的起始位置,而stm320518_eval.c下的全局变量GPIO_PORT被IAR编译成放在紧挨着的0x200000C0的位置。分别将IAP与APP烧录进FLASH,测试可以正常运行。
2 W: k; n' D4 Q; |! N# x% {2 ~  b
7 @6 B8 P4 @+ g注:从IAR工程的链接配置来看,并没有像KEIL那样配置RAM位置为:0x2000000,编译后的结果向量表也不会与其他全局变量相冲突,可见IAR编译器已经自动计算并避免这种冲突,不像KEIL那样会出现链接错误,以此来提示用户。5 ?2 e2 }& T$ B$ B8 O! z; A
8 Z- N( e/ X7 Z1 [
另外:在IAR下,在不存在IAP的情况下也是可以调试APP的,这点是KEIL所不具备的功能,看样子,IAR在细节的处理上比KEIL要好。* [( v/ r1 O1 n$ {+ D. N

) c0 s; t2 j! a* X# j
6 e3 d* @, N" w0 I( m  C3 n9 D4 Z5 }7 ?0 p
+ X; N4 b+ x  Y* l8 g4 Y, k
收藏 评论0 发布时间:2021-11-24 14:59

举报

0个回答

所属标签

相似技术帖

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