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

STM32在线升级(IAP)超详细图解 及 需要注意的问题...

[复制链接]
STMCU-管管 发布时间:2020-11-16 14:36
STM32在线升级(IAP)超详细图解 及 需要注意的问题解决
IAP 是啥7 y$ F2 E" C; ~# ~
  IAP( In Application Programming)即在应用编程,也就是用户可以使用自己的程序对MCU的中的运行程序进行更新,而无需借助于外部烧写器。其实ST官网也给出了IAP的示例程序,感兴趣的可以直接去官网搜索。( U2 P% B7 I6 F+ }% s2 Z
  这里有一点需要特殊注意,就是在MCU中,有一个特殊区域被称为 System memory。在这块区域中存放了ST公司自己的 bootloader 程序,它是在MCU出厂时,有ST固化到芯片中的,后续不能再更改。其中的 bootloader 程序也可以对MCU进行升级(DFU对芯片的编程应该就是用的这个Bootloader)。而且,芯片不同,BootLoader的功能也是有区别的。ST官网对于这些也是有详细文档的,后续再写篇文章介绍这一块。下图为部分芯片BootLoader版本及功能
4 q9 @3 H# g6 g" U8 Z在这里插入图片描述
$ I" ]9 |8 _8 W' _. C* k9 J- U2 G
12.png
STM32 MCU启动配置* p. k$ D+ `( x8 l
  要实现IAP,首先要了解一下MCU是如何启动的。这一点在芯片的参考手册中都有详细的说明,不同的芯片手册所在位置可能不同,但是一般在第二章会有单独一节叫Boot configuration。如下图:
3 \2 T+ M. x4 @0 o& VBootConfig' o: Y0 Y/ f8 e' d6 |; a; U
主要就是说,启动是通过管脚BOOT0和BOOT1的连接方式来控制的。这个是在硬件设计阶段设计好的。不同的配置决定了,MCU将何处映射到0x00000000。从这里又可以看到一点,MCU眼里只有0x00000000。至于为啥可以从Flash(0x08000000)启动,就是因为MCU内部做了映射。从其他位置启动时同理。
2 C- w2 l! g0 P6 J  e& ?
13.png
IAP 实现2 {4 z2 ]5 S) t& V; s) i! j3 _
  要实现IAP,则整个程序实现分为大程序(APP)和小程序(IAP)两部分。其中,APP主要接收升级数据并存储,IAP处理擦除APP,并重新写入升级数据。此外,IAP还应该可以独立接收升级数据的情况。但是,由于Cortex-M0核是没有中断向量表偏移寄存器的,这就导致了在Cortex-M0核的MCU上实现在线升级比较麻烦。在实际产品中,整个程序的基本组成结构:
! y0 u+ ]/ u5 E
14.png
实际的IAP流程如下:* B5 h+ q' E) Y8 ?/ j7 ~  s3 g
15.png
就是这么简单!
6 Z% v0 \6 q0 l4 T8 Y5 D/ p/ H1 D( ?! k( X$ ]4 c
  O3 I( B; N# v7 U
注意:
! r1 ?$ B# `& s# Q(1)与 Cortex-M3 和 Cortex-M4 不同,Cortex-M0 没有中断向量表偏移寄存器(VTOR寄存器)/ A8 F. Y+ M  Q& d' |$ S
(2)Cortex-M3 r2p0 及其之前版本,中断向量表只能位于SRAM或者CODE区域,但是Cortex-M3 r2p1及之后,Cortex-M4 没有该限制!
9 b/ [: q6 m5 E8 P+ e, l(3)MCU根据Boot引脚配置将指定地址映射为0x地址!5 H) H+ K. w6 a$ ~3 |
16.png
IAP 启动
  H! Q) P+ x& u6 z; t8 W; O$ m  启动网上有很多文章介绍,但是或多或少不是很完善,我只做了一张相对来说比较详细的图,如下:
: d! r+ V4 T, d6 t3 UStartup& j! s! [) T* _0 T9 ^3 v
  Cortex-M内核规定,中断向量表开始的4个字节存放的是堆栈栈顶的地址,其后是中断向量表各中断服务程序的地址。当发生中断后程序通过查找该表得到相应的中断服务程序入口地址,然后再跳到相应的中断服务程序中执行,中断服务程序中最终调用用户实现的各函数。例如:main函数就是复位中断服务函数中调用的!
( H; M) Y4 x, _$ d' y) ]  在没有IAP时,上电后从0x08000004处取出复位中断向量的地址,然后跳转到复位中断程序的入口(标号①所示),执行结束后跳转到main函数中(标号②所示)。通常main函数是个死循环,不会退出。在执行main函数的过程中发生中断,则STM32强制将PC指针指回中断向量表处(标号④所示),从中断向量表中找到相应的中断函数入口地址,跳转到相应的中断服务函数(标号⑤所示),执行完中断函数后再返回到main函数中来(标号⑥所示)。4 G% I. u: M( a9 y  M' @
  在添加IAP后,上电后仍然从0x08000004处取出复位中断向量的地址,然后跳转到复位中断程序的入口(标号①所示),执行结束后跳转到小程序的main函数中(标号②所示)。在执行小程序main函数的过程中发生中断,则STM32强制将PC指针指回中断向量表处(标号④所示),从中断向量表中找到相应的中断函数入口地址,跳转到相应的中断服务函数(标号⑤所示),执行完中断函数后再返回到main函数中来(标号⑥所示)。而想要大程序执行,则必须在小程序中显示强制跳转(标号⑦)。
! h5 F0 X# P7 {! S0 i9 y  在大程序的main函数的执行过程中,如果CPU得到一个中断请求,由于我们设置了中断向量表偏移量为N+M,因此PC指针被强制跳转到0x08000004+N+M处的中断向量表中得到相应的中断函数地址,再跳转到相应新的中断服务函数,执行结束后返回到main函数中来。4 r2 I. t/ h) z8 L3 D7 J8 q
  需要注意的是,复位中断比较特殊。产生复位后,PC的值会被硬件强制置为0x08000004。因为,在发生复位后,负责中断向量偏移的寄存器VTOR变为了0,因此,复位后的中断就变为了0x08000004。而其他中断发生时,VTOR为已经设置好的终端向量表偏移。
/ Q. B: p- s3 G) C
+ [& s- e- Y' {) S

/ [* h$ f1 B. L9 ]6 ^程序实现
7 K1 {* t1 ?' n* k+ l9 P2 d, ^  有了上面的介绍,实现就比较简单了!其实我有设计了一套适用于全部STM32芯片的IAP模板,但是属于公司产品,不方便对外公布!简单说几个重点:
+ s! `& O; j, V  B& t% I, ?" p8 i+ a2 z6 n  ~5 A5 E
9 p( y; q& c6 a+ p, x5 ?* F* j
使用 分散加载文件 实现起来会比较方便9 o6 b5 [) F8 [; _: z9 J) q, P; f
对于没有中断向量表偏移寄存器的MCU(主要是Cortex-M0核),一般采用将中断向量表复制到指定位置的内存中的方式实现:
, G+ C; c8 f7 F7 c' I' J使用分散加载文件在内存中指定一块区域:& X' N2 P. r6 Y& ^' Y
  1. #if   (defined ( __CC_ARM ))6 F5 S) A6 {9 m7 X2 D! l
  2.           __IO uint32_t VectorTable[48] __attribute__((section("SECTION_APP_VECTOR")));3 o1 |8 s% z5 b- A
  3.         #elif (defined (__ICCARM__))1 j) E7 S4 r( q
  4.         #pragma location = 0x20000000/ G0 B- C0 F. l4 N
  5.           __no_init __IO uint32_t VectorTable[48];
    ; e& P* X! w( D4 G
  6.         #elif defined   (  __GNUC__  )0 h9 _  A  T3 ^4 X6 [
  7.           __IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));
    $ p4 a+ x% p. P1 _( B# A# F" p6 U
  8.         #elif defined ( __TASKING__ )
    & A6 x+ N( Q% j
  9.           __IO uint32_t VectorTable[48] __at(0x20000000);
    # A5 y, }3 E4 Y( {) E! i! A
  10.         #endif
复制代码
+ O3 x* c$ l/ V+ L
2.将APP的终端向量表复制到以上位置,设置中断向量表重映射
9 e3 D$ i2 A) p- l2 D8 q) q; o
  1. static void SetVectorTable(void)
    , u) o$ _6 A* W! P5 z3 Q. ^0 L
  2. {
    # p2 G8 [- k3 y$ f* X" ^
  3.         int i;
    ! ~8 I8 K. ~3 `0 L4 b
  4. : N  @: z% V  b/ D
  5.         /*!< At this stage the microcontroller clock setting is already configured, % u! {1 o6 L6 G3 I8 j( Y$ ~( A; @& v
  6.         this is done through SystemInit() function which is called from startup! f+ K1 h% [6 A# X; s
  7.         file (startup_stm32f0xx.s) before to branch to application main.& \( S" ~6 X4 D  C, D1 Q
  8.         To reconfigure the default setting of SystemInit() function, refer to
    # R) j& l3 ]5 s6 W
  9.         system_stm32f0xx.c file$ {, ?, X* c: _5 C0 W# I- K$ m
  10.         */ 7 ^7 i0 l* O' A9 m3 u

  11. 8 R. X7 I  Y" K# I8 Y9 R
  12.         /* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/  7 Q- y* B6 T: h, D$ J
  13.         /* Copy the vector table from the Flash (mapped at the base of the application load address 0x08003000) to the base address of the SRAM at 0x20000000. *// V# r1 h: y5 P9 x' C
  14.         for(i = 0; i < 48; i++)
    ! g0 }0 s. f2 l6 n8 i! i: S* h# w
  15.         {' j% Q. B7 `- P0 \( N
  16.                 VectorTable[i] = *(__IO uint32_t*)(APP_SPACE_ADDR + (i<<2));4 ^! r/ }- D' ~0 W6 o
  17.         }2 T0 G8 M+ O7 B  \0 d
  18. " i/ |( _6 i4 @5 ]9 p1 a
  19.         /* Enable the SYSCFG peripheral clock */
    , v' i3 P# q/ v8 d8 v& Q$ x" t
  20.         RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);        /* 注意:ST官方例程使用 RCC_APB2PeriphResetCmd是不对的 */
    ( K0 }+ W- V7 r- l
  21.         /* Remap SRAM at 0x00000000 */
    7 z; _# h/ o8 v$ P1 w0 b
  22.         SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
    9 Z2 [# R0 L& o
  23. }
复制代码
% P9 E0 f0 X0 }, Z9 S
3.在由 IAP 跳转到 APP 时,一定注意把 IAP 中开启的外设全部关闭,否则在刚进入 APP中时,如果产生中断将导致死机等问题。 包括 SysTic 中断!!!包括 SysTic 中断!!!包括 SysTic 中断!!!这里可以做测试:
* k" o) s; C& l) o: S) G  u   1.测试一:IAP 中开启串口,然后用上位机不停的发送数据,在发送数据过程中执行 IAP 跳转 APP4 b* m0 R/ u* s1 [% b
   2.将 SysTick 中断 配置时间很短(微秒级别),当程序跳转到 APP 后,会出现 先产生 SysTick 中断,然后才会到 main 函数。此时如果 SysTick 中断中有相关代码,将导致出现错误!
  X' b' Z1 X2 S3 P8 M9 q( c3 y4 P5 t2 h2 @
4.STM32 的 back SRAM 在 IAP 中和 APP 中都初始化时,将导致 APP中的初始化不起作用。如果 IAP 中有使用,则在跳转 APP前必须反初始化。
) Y4 A# V4 e. S2 D/ V& G/ ]8 F% C$ L' q; `( O- }1 ]

9 E) E2 {. G6 ?7 a! b
8 A1 g+ W/ E; {: l6 k
/ J3 b- a, r( `) a1 M3 h
9 b  e9 R5 B$ _4 ^' a! c

" Y: ]% s4 ], s
) v' C4 m1 c) Q: J6 q+ U
赞 收藏 3 评论0 发布时间:2020-11-16 14:36

举报

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