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

【经验分享】STM32 IAP固件升级(一)

[复制链接]
STMCU小助手 发布时间:2022-1-15 22:19
章节说明
STM32 IAP固件升级实验分为一下的章节(加粗的字体是本章节的内容):
一、Flash和RAM的区域划分、工程建立、程序分散加载、程序烧写
二、Stm32 bootloader、application、firmware 程序的分析和编写
三、使用DMA收发串口的不定长数据
四、通信协议的设计
五、STM32 IAP程序的设计
* M0 \/ f$ I/ i8 N. G' l六、上位机的程序的编写% x6 ^: X/ Z  u) y4 s
& V/ b- k0 F, i2 t; }9 M- A
一、Flash区域的划分1.区域划分
  • 实验使用的是 STM32F103VET6型号的MCU。这个单片机的型号的内部flash的大小是512Kb, RAM的大小是64Kb。
  • 因为一般使用的都是flash的启动方式(即flash 的起始地址0x0800 0000被映射到 0x0000 0000。STM32的启动方式可以查看《STM32中文参考手册》) 所以flash的区域划分如下:2 ~+ Z4 |- s6 i( E
1627979-20200118160928915-2018591605.jpg
3 Y# V$ z! d1 a3 f$ F3 d2. flash 分区说明
  • 0x0800 0000 到 0x0800 b7FF 地址的flash块划分给bootloader,大小是46kb
  • 0x0800 B800 到 0x0800 BFFF 的flash块划分为参数表(parameters),大小是2Kb
  • 0x0800 C000 到 0x0804 3FFF 的flash块划分为应用程序区 (application),大小是224Kb
  • 0x0804 4000 到 0x0807 BFFF 的flash块划分为程序升级区 (update region),大小跟应用程序区一样 224kb
  • 0x0807 C000 到 0x0807 FFFF 的flash块划分为固件区(firmware),大小是16Kb
    3 G. b, R4 E2 u! F. C
3. 每个分区作用
  • bootloader 启动加载程序,主要用来加载和启动应用程序,还有更新应用程序
  • parameters 主要用来记录信息,bootloader 和 application 的信息交互
  • application 应用程序区,主要用来实现所需要的业务的程序
  • update region 程序更新区,主要存放更新下载的程序,当然也可以直接下载到 application 区,但是如果更新失败了,应用程序就不能执行了。所以单独划分一块区域,存放更新下载的序,更新完后再覆盖到application然后复位运行
  • firmware 固件区,主要存放一些函数接口,用户可以通过函数指针直接调用。像tiny-4412、smart210、esp32等这些板子的芯片在irom里面都提供了一些函数接口,通过地址可以直接调用这些函数。( E# d; F. f, ]) D
二、RAM内存的划分4 b+ N' T. l/ O  z( N
1、区域划分
RAM(内存)的起始地址是 0x2000 0000,大小是64Kb。在实验主要将它划分为两块。一块是从 0x2000 0000 到 0x2000 FBFF 大小是63Kb。另一块是从 0x2000 FC00 到 0x2001 0000 大小是 1Kb,划分如下图
1627979-20200118161003642-847963352.jpg
2、区域的作用
  • 63Kb这块内存区域主要是用于 bootloader 和 application 应用程序的可读可写段(RW),未初始化或者初始化为0的数据段(ZI)、堆空间、栈空间
  • 1kb这块内存区域主要是用于 firmware 区域的可读可写段(RW),未初始化或者初始化为0的数据段(ZI)
  • 注意:firmware因为没有初始化堆,所以不能使用malloc这类堆内存管理函数。
    2 M" W* O. Q: L
3、简单说明
  • 因为STM32的flash 是norflash 读的时候可以像内存一样读,但是写的时候不能像内存那样子写,所以这些 RW 段 ZI 段都是加载到内存里。加载到哪里,这是由分散加载文件.sct文件(和链接脚本一个意思)里面说明。至于怎么加载 ,stm32 函数库的start_up.s文件的__main 到 main函数的过程就是加载数据到RAM空间。后面再介绍.sct文件* h$ i# {. C: _7 @6 ~- }4 L4 H
三、工程建立
工程中需要三个project,分别是 bootloader application firmware 如下图:
1627979-20200118161053289-1264155561.jpg 2 `8 m$ f9 t; `0 h
四、分散加载
因为程序存放在不同的区域了,并且每段区域的程序是独立的,所以在链接每个程序的时候需要告诉连接器,程序怎么放,程序加载启动的时候又应该怎么加载,堆区和栈区的位置这些都要告诉链接器。我们可以通过分散加载文件.sct 文件来告诉链接器。下面来看一下这个文件
1.原来的分散加载文件. u# ?# x; V9 M$ \. D2 J6 a$ I
  1. ; *************************************************************
    ' a3 L$ d( Q5 ]$ o9 N- ^7 U( U4 y
  2. ; *** Scatter-Loading Description File generated by uVision ***
    " i& u4 M( _7 z7 w
  3. ; *************************************************************- e7 {2 l, n% ~% T# S) S
  4. ;LR_IROM1 段名/域名" y; e  b1 E1 ~6 E
  5. ;0x08000000 程序加载的起始地址+ Q7 p2 o$ {3 R4 d. j/ R" g! g. n$ m
  6. ;0x00080000 加载域的大小: j7 T' N; q* U8 D" r$ P
  7. LR_IROM1 0x08000000 0x00080000  {    ; load region size_region
    : M; g! t. s3 D& s  Y& A
  8.   ;ER_IROM1 执行域的名称  
    ; i" h$ T9 m& B; P, s3 I- b' [
  9.   ;0x08000000 程序的执行起始地址
    9 y6 q3 Y( L- `6 c' F9 u7 j2 j; {
  10.   ;0x00080000 执行域的大小* v8 j! e* B" g. |& \. s. x  x
  11.   ;一般程序是在 flash 里面运行的所以 程序的执行地址等于加载地址,如果想要让程序运行在RAM中,执行地址修改为RAM的地址  o1 `7 k% E) v2 U1 W& z
  12.   ER_IROM1 0x08000000 0x00080000  {  ; load address = execution address; e  j. L/ [2 g4 z1 |6 o* t
  13.    ;下面就是指定某些段怎么链接了
    . d; \, w& o" c( |# {) H# M- y, B* ~* }
  14.    *.o (RESET, +First)   ;链接的时候最先存放的是 所有.o文件的RESET段,紧跟的是First段(RESET段在start_up.s文件中有定义), J% z' x9 Y) B" S) F. f! t6 F
  15.    *(InRoot$Sections)   ;然后存放 __main 到 main的这段代码,这段代码主要是将flash的RW和ZI段加载到RAM中; _" Y; u, D* w% S% M* U5 P
  16.    .ANY (+RO)            ;紧跟着的是所有文件的只读数据(RO段),一般是向量表、代码段和常量(字符串常量,和const修饰的数据)
    & R* h8 S7 F4 `( k8 H: T+ D
  17.   }
    # V+ l4 T1 T& C
  18. ;RW_IRAM1 可读可写数据的段名# N. q: j: T  v. z5 T
  19. ;0x20000000起始地址  
    6 d) {9 \+ l) O7 I$ @0 A6 B
  20. ;0x00010000大小
    $ F. w  f9 U: q- Y/ v& I
  21.   RW_IRAM1 0x20000000 0x00010000  {  ; RW data
    . x5 u( ?0 O3 {; L5 T5 P7 [
  22.    .ANY (+RW +ZI);紧接着的是(RW段),(ZI)段
    7 k+ \6 _% |, Y4 {2 g
  23.   }1 ^( O+ J( K8 j$ s, m
  24. }
    5 E4 [$ f: q* c
  25. 5 n8 H$ H2 _' U$ s  Y
复制代码

8 I$ z+ t. _, |+ }- @& n6 ~3 e
Region的名称可以自己定义或者修改,重要的是地址要分配对就可以了。: p# L: k$ i, K2 a/ m' }0 n
Heart_of_Eagle这位博主有一篇比较详细的博文值得参考,不过不是MDK的sct文件的,原理都是大同小异& d: Y- o8 o8 v/ O# Z! x3 G
MDK也是有详细的帮助文档,不过是纯英文的,想用好sct可以阅读里面的内容. W  z& ]! o8 X. c
1.
1627979-20200118161128852-617757783.png
# N4 Z% U$ x( Y5 G- ?3 c
: Q; W7 t  Q; P
2.
1627979-20200118161146238-1228850186.png
8 _3 g- I% d5 h' n- i9 E
2.修改bootloader的分散加载文件
根据上面的flash和RAM的划分修改sct加载文件,如下代码块:
  1. ; *************************************************************' ~# R4 ~! q( i. V! x9 I3 }
  2. ; *** Scatter-Loading Description File generated by uVision ***# z9 m- D+ a2 t
  3. ; *************************************************************3 [2 E% f$ o" H, ~, |6 G0 x% w2 A
  4. ;因为bootloader是第一个启动的程序,而且机器上电复位的时候是从0x0800 0000开始执行(因为被映射到了0x0000 0000)地址  @1 {. E9 E9 q2 V% [$ b) b( x$ o
  5. ;所以bootloader加载域的起始地址和执行地址都是0x0800 0000
    1 o, o- H, h' P7 R# o0 y, w2 F
  6. ; 0x0000B800域的大小(46kb)也是通过上面的设计的分区来填写5 Y9 n  g( _  a! r
  7. LR_IROM1 0x08000000 0x0000B800  {    ; load region size_region
    % ?; {; A. @+ D8 {' M
  8.   ER_IROM1 0x08000000 0x0000B800  {  ; load address = execution address) ?% n: b) u* f4 I, {, S- ?1 B3 n
  9.    ;里面段的存放位置使用默认的就可以
    , X& e% D& ~7 e& s) f# C& d
  10.    *.o (RESET, +First)
    , S* n& O2 x6 n
  11.    *(InRoot$Sections)# M+ L# |! d2 ]5 q5 |: u
  12.    .ANY (+RO)# l1 u- b0 \  U3 s
  13.   }0 [; ?$ z9 t/ z1 }" A) [- {* n
  14. ; 0x20000000 这个也是根据上面的RAW的分区填写,
    " h5 k4 X1 j/ I0 j* |5 x: O) w. x7 ~' c
  15. ;0x0000FC00 大小是 63Kb
    $ R8 l6 U/ g* a+ a5 i1 I) w) a) Z
  16.   RW_IRAM1 0x20000000 0x0000FC00  {  ; RW data
    ! z' w' P2 I2 T
  17.    ;段的存放位置使用默认的就可以了3 B2 L. q. y; {+ k
  18.    .ANY (+RW +ZI)3 ]1 Z) ~9 k7 d' E! k" S6 N' H2 M
  19.   }( m# ]1 g5 _- W: F
  20. }7 \/ n1 t' J" d  ^' t( {$ N
复制代码
: Q- O3 v4 F/ E2 U3 y. ~: a( Z% [/ c

: }+ T' O) `9 ?5 Z0 t3.修改application的分散加载文件
修改如下,跟bootloader一样,就不啰嗦了
  1. ; *************************************************************3 i6 `  S* I4 H& `9 j2 b
  2. ; *** Scatter-Loading Description File generated by uVision ***$ g- C7 V+ W& Q
  3. ; *************************************************************3 f' u% J+ F( Y$ c
  4. LR_IROM1 0x0800C000 0x00038000  {    ; load region size_region
    ' w$ N& d! ]; m1 ~
  5.   ER_IROM1 0x0800C000 0x00038000  {  ; load address = execution address
    * }% {8 g# _6 o
  6.    *.o (RESET, +First)# u: L* }+ e5 t6 r2 b
  7.    *(InRoot$Sections)6 d9 t9 [4 i8 H/ J3 Y- C' a
  8.    .ANY (+RO)$ N! a7 i9 L4 ]
  9.   }
    % M$ S7 ^, r  y2 g  X) S' d: ]2 R" a/ S
  10.   RW_IRAM1 0x20000000 0x0000FC00  {  ; RW data    0x0000FC00
    ! @/ j! Z5 w, m/ m1 L# x
  11.    .ANY (+RW +ZI)' J, Z- G" X( p* t" W
  12.   }  ~5 T3 x# ?& s: Q% d7 ]  F
  13. }. F( y4 F* ?& c- c3 t9 u# |' P6 J
复制代码

% }( ?) d' F- [2 C
$ z4 T1 w) T. Q4.修改firmware的分散加载文件
*(InRoot$$Sections) 被注释掉了,因为 firmware 的程序是没有 __main 到 main 函数部分的代码的。下一章节写程序的时候会有讲解。其他的内容也跟bootloader文件差不多,上面的分区来写就可以了
  1. ; *************************************************************3 q" h# J  I9 H+ B( Q1 h
  2. ; *** Scatter-Loading Description File generated by uVision ***1 z2 @$ ~' k4 H0 K
  3. ; *************************************************************
    + }8 d0 a& w+ s( S

  4. * D' w3 f- P2 @9 K. z' _) r* n; k
  5. LR_IROM1 0x0807C000 0x00004000  {    ; load region size_region4 F" X# W% g* ?2 w4 W
  6.   ER_IROM1 0x0807C000 0x00004000  {  ; load address = execution address
    ) O# N7 U" s1 U- m. F8 C
  7.    *.o (RESET, +First)
    & S- q2 C, u; X. W! R" \0 W4 [5 ]
  8.    ;*(InRoot$Sections) ( ^1 y1 n5 t! p; ^
  9.    .ANY (+RO)
    , B1 m  n+ e# z8 R8 u* w: ~& L
  10.   }
    + D! c5 ?* E5 |: z' v
  11.   RW_IRAM1 0x2000FC00 0x00000400  {  ; RW data  % f% Z5 V! n2 S
  12.    .ANY (+RW +ZI)
    % u2 J# t$ ~+ v$ W3 s5 E9 ~* d
  13.   }( T9 u9 b+ g8 g4 S; v6 x0 k1 ^
  14. }% h; A. d( I4 Y$ b3 G
复制代码

8 A. j0 H4 y2 q& @! ^* T: n2 L; u- D% m
5. 注意事项
在MDK的默认设置里,链接的时候是不使用分散加载文件的 xxx.sct 文件。要使用 xxx.sct 文件需要将下面的设置去掉
LLK)B5}W)WA(Z28_DYZVX0H.png
3 K- y- d/ X) R. W* j. Z# K8 G
五、程序的下载设置
  • 由于本章还没实现IAP这部分的程序,所以 bootloader、application 和 firmware的程序都是使用烧写器来烧写到falsh的不同区域。所以需要设置一下。
  • 设置的地址跟大小也是根据上面的flash分区来设置的。
  • 主要设置MDK里面的 Debug -> Flash Download 的这两个地方,设置完这里就可以用Jlink将不同的程序烧写到不同的区域了。
  • 下图是 bootloader 的设置,其他两个也是根据实际来设置
    6 W. |- t# {" D& x %IM8%5@HK}METIUD`XBCXXG.png 8 n  }/ a. k' E
六、实验现象
说了这么多先来个实验现象吧, 对于下面的程序分析和编写就下一章再写了。) w  [7 `7 P, H& K1 [
工程文件已经上传到码云---->/ S+ _9 N. d( @- `6 P. w5 B
代码可能存在问题,有问题可以留言讨论。
  • hello bootloader 是在bootloader运行的时候打印出来的,打印完后就跳到应用程序执行了
  • num = 10和 num1 = 0 这两个值是通过函数指针调用firmware固件区的函数接口来获取的
  • 打印完上面的两个值之后循环打印hello app
    4 D3 b, G# M3 N- [1 _8 A1 @现象如下图:5 S; n. s4 q5 j/ x6 ^" Y. {# ]0 d
    T6PYBAQPXKFJ3H`NS)G6C2H.png
    2 @* ~' G' t0 B+ k3 o1 M5 N2 {1 l, }6 @
8 A' l" q- L3 p' l7 F

- t, \3 u- Q- o1 y$ m  t
赞 收藏 1 评论0 发布时间:2022-1-15 22:19

举报

0个回答

所属标签

相似技术帖

官网相关资源

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