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

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

[复制链接]
STMCU-管管 发布时间:2020-11-16 14:36
STM32在线升级(IAP)超详细图解 及 需要注意的问题解决
IAP 是啥
) y: J4 g3 J* m0 w% ^) o% H- F  IAP( In Application Programming)即在应用编程,也就是用户可以使用自己的程序对MCU的中的运行程序进行更新,而无需借助于外部烧写器。其实ST官网也给出了IAP的示例程序,感兴趣的可以直接去官网搜索。
! I# v( e, U6 D% I! I. J4 n  这里有一点需要特殊注意,就是在MCU中,有一个特殊区域被称为 System memory。在这块区域中存放了ST公司自己的 bootloader 程序,它是在MCU出厂时,有ST固化到芯片中的,后续不能再更改。其中的 bootloader 程序也可以对MCU进行升级(DFU对芯片的编程应该就是用的这个Bootloader)。而且,芯片不同,BootLoader的功能也是有区别的。ST官网对于这些也是有详细文档的,后续再写篇文章介绍这一块。下图为部分芯片BootLoader版本及功能3 a# @# n! ~% a. e
在这里插入图片描述) A* Y& {+ |- m3 e
12.png
STM32 MCU启动配置  B$ W: Z5 a/ U! f* o, j  T
  要实现IAP,首先要了解一下MCU是如何启动的。这一点在芯片的参考手册中都有详细的说明,不同的芯片手册所在位置可能不同,但是一般在第二章会有单独一节叫Boot configuration。如下图:
9 b$ L0 A7 u8 d% o4 {: dBootConfig
3 h* ^; F# X; a: s; X主要就是说,启动是通过管脚BOOT0和BOOT1的连接方式来控制的。这个是在硬件设计阶段设计好的。不同的配置决定了,MCU将何处映射到0x00000000。从这里又可以看到一点,MCU眼里只有0x00000000。至于为啥可以从Flash(0x08000000)启动,就是因为MCU内部做了映射。从其他位置启动时同理。; h2 i5 G  @+ x" D. }
13.png
IAP 实现
' a* N3 C4 X! b  要实现IAP,则整个程序实现分为大程序(APP)和小程序(IAP)两部分。其中,APP主要接收升级数据并存储,IAP处理擦除APP,并重新写入升级数据。此外,IAP还应该可以独立接收升级数据的情况。但是,由于Cortex-M0核是没有中断向量表偏移寄存器的,这就导致了在Cortex-M0核的MCU上实现在线升级比较麻烦。在实际产品中,整个程序的基本组成结构:7 i' g5 N/ N+ w, v
14.png
实际的IAP流程如下:% H) h& K) d- G4 E9 @1 X1 g
15.png
就是这么简单!
/ u6 C! G* h5 L$ l& Z0 i7 R0 Y8 s/ W+ r" E; l; i
+ b' R( o! Y( w& b) Z6 c
注意:5 K2 v: Z4 c" t5 C4 a8 x  Q, G
(1)与 Cortex-M3 和 Cortex-M4 不同,Cortex-M0 没有中断向量表偏移寄存器(VTOR寄存器)+ z4 d4 C# Z) ?8 Y3 |. m
(2)Cortex-M3 r2p0 及其之前版本,中断向量表只能位于SRAM或者CODE区域,但是Cortex-M3 r2p1及之后,Cortex-M4 没有该限制!
4 z5 Q' |# V8 v. a! e: j8 L(3)MCU根据Boot引脚配置将指定地址映射为0x地址!
/ x: o, C+ C+ u7 x0 S! f
16.png
IAP 启动( X6 @0 i9 b/ d2 w3 F
  启动网上有很多文章介绍,但是或多或少不是很完善,我只做了一张相对来说比较详细的图,如下:
) \3 m% O/ Q2 f1 Q; g; vStartup
7 a! Y0 Z+ ~2 q0 v7 W8 c. e  Cortex-M内核规定,中断向量表开始的4个字节存放的是堆栈栈顶的地址,其后是中断向量表各中断服务程序的地址。当发生中断后程序通过查找该表得到相应的中断服务程序入口地址,然后再跳到相应的中断服务程序中执行,中断服务程序中最终调用用户实现的各函数。例如:main函数就是复位中断服务函数中调用的!
4 N+ @2 m4 s; Q5 b& B  在没有IAP时,上电后从0x08000004处取出复位中断向量的地址,然后跳转到复位中断程序的入口(标号①所示),执行结束后跳转到main函数中(标号②所示)。通常main函数是个死循环,不会退出。在执行main函数的过程中发生中断,则STM32强制将PC指针指回中断向量表处(标号④所示),从中断向量表中找到相应的中断函数入口地址,跳转到相应的中断服务函数(标号⑤所示),执行完中断函数后再返回到main函数中来(标号⑥所示)。
% U4 j; K' ]4 f% v1 j* @  在添加IAP后,上电后仍然从0x08000004处取出复位中断向量的地址,然后跳转到复位中断程序的入口(标号①所示),执行结束后跳转到小程序的main函数中(标号②所示)。在执行小程序main函数的过程中发生中断,则STM32强制将PC指针指回中断向量表处(标号④所示),从中断向量表中找到相应的中断函数入口地址,跳转到相应的中断服务函数(标号⑤所示),执行完中断函数后再返回到main函数中来(标号⑥所示)。而想要大程序执行,则必须在小程序中显示强制跳转(标号⑦)。
' w' j+ m, A1 b  在大程序的main函数的执行过程中,如果CPU得到一个中断请求,由于我们设置了中断向量表偏移量为N+M,因此PC指针被强制跳转到0x08000004+N+M处的中断向量表中得到相应的中断函数地址,再跳转到相应新的中断服务函数,执行结束后返回到main函数中来。. C' v( W! Z4 t1 X1 v4 e: G( |
  需要注意的是,复位中断比较特殊。产生复位后,PC的值会被硬件强制置为0x08000004。因为,在发生复位后,负责中断向量偏移的寄存器VTOR变为了0,因此,复位后的中断就变为了0x08000004。而其他中断发生时,VTOR为已经设置好的终端向量表偏移。5 d6 G1 K2 Z. c; n- |+ {
; i' q$ D  K! f; O' A  ~) w
4 X/ X7 F7 `- |- I" ~% D9 m9 K
程序实现
* q- H: {' m+ M- Y4 x  有了上面的介绍,实现就比较简单了!其实我有设计了一套适用于全部STM32芯片的IAP模板,但是属于公司产品,不方便对外公布!简单说几个重点:0 ^# [/ E7 |9 V8 c  t

" ^, m' ]: f  P$ {

5 L$ S- U% i0 I% z7 y4 t使用 分散加载文件 实现起来会比较方便
4 A* T8 K1 K6 B: o3 h/ ^对于没有中断向量表偏移寄存器的MCU(主要是Cortex-M0核),一般采用将中断向量表复制到指定位置的内存中的方式实现:
' v8 k5 u* A0 E使用分散加载文件在内存中指定一块区域:8 \( C2 [: S5 ^2 E. x! K
  1. #if   (defined ( __CC_ARM ))/ K. R! m9 n6 s, t
  2.           __IO uint32_t VectorTable[48] __attribute__((section("SECTION_APP_VECTOR")));$ n2 L( p6 R* I
  3.         #elif (defined (__ICCARM__))+ F- d' J7 N0 l8 J( V9 Y) N
  4.         #pragma location = 0x200000009 H, F" P' B0 n; z7 \8 }
  5.           __no_init __IO uint32_t VectorTable[48];9 N- P% C# e; G: i
  6.         #elif defined   (  __GNUC__  )
    , b4 U& p* N# x) D: l
  7.           __IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));
    ) ^7 [( i  \9 x8 K3 R: o$ X
  8.         #elif defined ( __TASKING__ )
      [. D$ m( m$ W( d& ?
  9.           __IO uint32_t VectorTable[48] __at(0x20000000);
    ! t4 t* {6 m3 \" I9 F
  10.         #endif
复制代码

0 W- x  y* B% _6 [& ^7 c2.将APP的终端向量表复制到以上位置,设置中断向量表重映射5 ]0 n, o' Z( A4 v6 s6 C- `
  1. static void SetVectorTable(void)
    1 _* Z0 O2 i0 X9 n7 E
  2. {
    ( I* i6 E* N% P/ h! L9 _
  3.         int i;  ~! s8 z8 s9 S0 k. ?% b7 U
  4. ( M/ B$ {9 m' l4 N7 h9 N# q$ }
  5.         /*!< At this stage the microcontroller clock setting is already configured,
    ' ~' F) {, Y; y# K% u9 w
  6.         this is done through SystemInit() function which is called from startup
    1 u# B+ C5 [! ^2 v; y1 U7 c
  7.         file (startup_stm32f0xx.s) before to branch to application main.
    % D5 u$ j8 q( t2 y' d
  8.         To reconfigure the default setting of SystemInit() function, refer to# P  D5 t+ \+ H+ Q. }# e9 _+ [
  9.         system_stm32f0xx.c file
    $ S/ `* W$ z  k  ?4 t
  10.         */ ' A3 |+ Q4 W4 Z$ b5 z8 u, J5 E7 H
  11. 7 d+ l" S9 c1 u4 y
  12.         /* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/  " z; X% w: M$ x3 Z; 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. */
    4 M5 }1 O4 z; o% X$ D! X7 b
  14.         for(i = 0; i < 48; i++)3 N% P! W6 B. V% V. V% r; O
  15.         {
    & _- t% @+ _# H% ?
  16.                 VectorTable[i] = *(__IO uint32_t*)(APP_SPACE_ADDR + (i<<2));
    0 ]3 T5 W" w7 \& p! X6 a
  17.         }& ^4 |: t* {1 z& M4 G  K) w
  18. # p0 I$ `; c/ d, ~1 r
  19.         /* Enable the SYSCFG peripheral clock */' C3 U. i6 p9 g; c5 D$ o- V
  20.         RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);        /* 注意:ST官方例程使用 RCC_APB2PeriphResetCmd是不对的 */8 M7 S* T, b7 K) F5 V, H
  21.         /* Remap SRAM at 0x00000000 */- ]# T% x7 Z4 N6 p1 \5 b1 }/ M3 @
  22.         SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);% s1 {5 E9 _+ h8 @
  23. }
复制代码

, H/ k, r& w+ ~' g6 H3.在由 IAP 跳转到 APP 时,一定注意把 IAP 中开启的外设全部关闭,否则在刚进入 APP中时,如果产生中断将导致死机等问题。 包括 SysTic 中断!!!包括 SysTic 中断!!!包括 SysTic 中断!!!这里可以做测试:
6 p8 E6 y4 R; T& }1 S   1.测试一:IAP 中开启串口,然后用上位机不停的发送数据,在发送数据过程中执行 IAP 跳转 APP
8 a: }; H6 w* N+ ?   2.将 SysTick 中断 配置时间很短(微秒级别),当程序跳转到 APP 后,会出现 先产生 SysTick 中断,然后才会到 main 函数。此时如果 SysTick 中断中有相关代码,将导致出现错误!, l4 P: }' V; C2 }* y+ d1 e+ z

- N1 a0 Q3 f( ]5 v- A4.STM32 的 back SRAM 在 IAP 中和 APP 中都初始化时,将导致 APP中的初始化不起作用。如果 IAP 中有使用,则在跳转 APP前必须反初始化。- l! Z$ T0 V9 Y8 G

% S( Z$ ]' E( `( H7 v
4 _- W, `  k! B% d3 `

6 J0 x8 D' a4 n  u3 E: x' P8 t
$ A& W2 v& u9 E* @& D$ u; E6 E$ f- N

" N) j" H. V8 I4 p4 ~

7 [5 x0 r! A2 l7 E+ z5 A3 Z5 Q6 P" }7 q) U: T
收藏 3 评论0 发布时间:2020-11-16 14:36

举报

0个回答

所属标签

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