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

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

[复制链接]
STMCU小助手 发布时间:2022-1-15 22:19
章节说明
STM32 IAP固件升级实验分为一下的章节(加粗的字体是本章节的内容):
一、Flash和RAM的区域划分、工程建立、程序分散加载、程序烧写
二、Stm32 bootloader、application、firmware 程序的分析和编写
三、使用DMA收发串口的不定长数据
四、通信协议的设计
五、STM32 IAP程序的设计4 T% p( V+ q+ t2 |2 x  a
六、上位机的程序的编写
6 \4 I' O4 K' l3 f" \) ?+ m2 }
: I9 z! {9 n& j/ c
一、Flash区域的划分1.区域划分
  • 实验使用的是 STM32F103VET6型号的MCU。这个单片机的型号的内部flash的大小是512Kb, RAM的大小是64Kb。
  • 因为一般使用的都是flash的启动方式(即flash 的起始地址0x0800 0000被映射到 0x0000 0000。STM32的启动方式可以查看《STM32中文参考手册》) 所以flash的区域划分如下:
    6 j$ i. A" Q; Q6 j
1627979-20200118160928915-2018591605.jpg 0 f- t/ B( `- `: t+ k
2. 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* I) _$ \" p" B
3. 每个分区作用
  • bootloader 启动加载程序,主要用来加载和启动应用程序,还有更新应用程序
  • parameters 主要用来记录信息,bootloader 和 application 的信息交互
  • application 应用程序区,主要用来实现所需要的业务的程序
  • update region 程序更新区,主要存放更新下载的程序,当然也可以直接下载到 application 区,但是如果更新失败了,应用程序就不能执行了。所以单独划分一块区域,存放更新下载的序,更新完后再覆盖到application然后复位运行
  • firmware 固件区,主要存放一些函数接口,用户可以通过函数指针直接调用。像tiny-4412、smart210、esp32等这些板子的芯片在irom里面都提供了一些函数接口,通过地址可以直接调用这些函数。
    0 D+ y& U! U7 Z, F2 U% y( K% X" d
二、RAM内存的划分
3 u0 o* ~: V. i. e' Y4 a! I1、区域划分
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这类堆内存管理函数。1 G$ O6 l1 V; Z" c7 d4 Y& w
3、简单说明
  • 因为STM32的flash 是norflash 读的时候可以像内存一样读,但是写的时候不能像内存那样子写,所以这些 RW 段 ZI 段都是加载到内存里。加载到哪里,这是由分散加载文件.sct文件(和链接脚本一个意思)里面说明。至于怎么加载 ,stm32 函数库的start_up.s文件的__main 到 main函数的过程就是加载数据到RAM空间。后面再介绍.sct文件
    ( X, s6 i  k6 v+ u" U/ O
三、工程建立
工程中需要三个project,分别是 bootloader application firmware 如下图:
1627979-20200118161053289-1264155561.jpg
# f7 {3 I% ^6 f' u1 I; i6 `
四、分散加载
因为程序存放在不同的区域了,并且每段区域的程序是独立的,所以在链接每个程序的时候需要告诉连接器,程序怎么放,程序加载启动的时候又应该怎么加载,堆区和栈区的位置这些都要告诉链接器。我们可以通过分散加载文件.sct 文件来告诉链接器。下面来看一下这个文件
1.原来的分散加载文件2 k" ^, O+ K! E: H$ m
  1. ; *************************************************************; A! H$ |- G" [: A! M' R! v
  2. ; *** Scatter-Loading Description File generated by uVision ***4 |- I. c, K$ k, U2 @
  3. ; *************************************************************
    : W2 K2 u0 K7 x0 a+ e: o  ?
  4. ;LR_IROM1 段名/域名
    % z2 y- E9 t7 @" C9 v& J+ N3 W
  5. ;0x08000000 程序加载的起始地址/ b  Q* r3 b; J/ p( P0 y+ |; B. B
  6. ;0x00080000 加载域的大小
    ( S, B7 @; M3 y$ D3 z
  7. LR_IROM1 0x08000000 0x00080000  {    ; load region size_region6 k0 H' z, k  @+ X3 [) f
  8.   ;ER_IROM1 执行域的名称  
    5 `; v' C) {; c$ ~3 g
  9.   ;0x08000000 程序的执行起始地址- C. ?9 f, h: O2 L! U
  10.   ;0x00080000 执行域的大小
    ! U% O& F3 c; b/ F9 O
  11.   ;一般程序是在 flash 里面运行的所以 程序的执行地址等于加载地址,如果想要让程序运行在RAM中,执行地址修改为RAM的地址
    + O; H3 ?3 ]3 B5 |
  12.   ER_IROM1 0x08000000 0x00080000  {  ; load address = execution address& D  A2 L: `- {5 Y# M( p+ P
  13.    ;下面就是指定某些段怎么链接了7 O2 z# y% K# ]& {# `
  14.    *.o (RESET, +First)   ;链接的时候最先存放的是 所有.o文件的RESET段,紧跟的是First段(RESET段在start_up.s文件中有定义)
    9 K7 b7 m5 v3 T. N
  15.    *(InRoot$Sections)   ;然后存放 __main 到 main的这段代码,这段代码主要是将flash的RW和ZI段加载到RAM中, M2 @  _. s2 ~9 f" K0 s2 }6 \
  16.    .ANY (+RO)            ;紧跟着的是所有文件的只读数据(RO段),一般是向量表、代码段和常量(字符串常量,和const修饰的数据)
    2 I; k* b# S, |2 ]* I7 a
  17.   }% l7 r- P. ^8 S$ w
  18. ;RW_IRAM1 可读可写数据的段名' \$ K& ~' r1 C
  19. ;0x20000000起始地址    F6 W9 Q7 Y- @  c, M
  20. ;0x00010000大小
    ( v% c9 V4 ~* M
  21.   RW_IRAM1 0x20000000 0x00010000  {  ; RW data
      b  a" C3 ]% X$ d, u; {
  22.    .ANY (+RW +ZI);紧接着的是(RW段),(ZI)段$ [7 M4 M% c9 S: U. p0 c1 a
  23.   }
    , t! P: `. t3 m* |
  24. }
    " i4 `2 ~. n2 G/ V3 Z

  25. 2 U( u' K- X; f6 N( ?' ]* v. D2 W
复制代码
/ @  m& ?! U1 m4 }1 f( z  W
Region的名称可以自己定义或者修改,重要的是地址要分配对就可以了。$ N& C- }, t$ @- c. W9 m1 R5 H
Heart_of_Eagle这位博主有一篇比较详细的博文值得参考,不过不是MDK的sct文件的,原理都是大同小异" q6 d9 N9 a9 j8 v7 c: ~
MDK也是有详细的帮助文档,不过是纯英文的,想用好sct可以阅读里面的内容
9 ?/ k6 h  {, i4 N
1.
1627979-20200118161128852-617757783.png ' B% g% d7 k7 W' E/ }: w
9 d3 c1 o5 h4 X0 y
2.
1627979-20200118161146238-1228850186.png
2 h  V) ?! t4 x/ @
2.修改bootloader的分散加载文件
根据上面的flash和RAM的划分修改sct加载文件,如下代码块:
  1. ; *************************************************************
    7 I% F/ Y4 U" ]' N( B
  2. ; *** Scatter-Loading Description File generated by uVision ***
    0 N% B5 S; F, v5 I' m: F. e' A8 N
  3. ; *************************************************************
    - ]$ P& M, [4 |# z* V9 x
  4. ;因为bootloader是第一个启动的程序,而且机器上电复位的时候是从0x0800 0000开始执行(因为被映射到了0x0000 0000)地址
    / Q, \2 z* J! l2 e; O( ^$ k& Q
  5. ;所以bootloader加载域的起始地址和执行地址都是0x0800 0000* f: c9 S% }0 k2 O. N; G: X' X
  6. ; 0x0000B800域的大小(46kb)也是通过上面的设计的分区来填写
    % f  N( X) X* H  f! W3 m
  7. LR_IROM1 0x08000000 0x0000B800  {    ; load region size_region3 Z9 F2 L) x3 J" q7 z9 }4 ]
  8.   ER_IROM1 0x08000000 0x0000B800  {  ; load address = execution address
    % S$ Z7 {7 L+ p( P
  9.    ;里面段的存放位置使用默认的就可以( Z! B8 F! z8 W. n2 l, T
  10.    *.o (RESET, +First)1 f+ |8 H# Z- q+ r9 z
  11.    *(InRoot$Sections)4 F- g  L$ z0 s
  12.    .ANY (+RO)
    9 O- Y8 u7 C2 d. i9 C& g
  13.   }
    ! M' i1 v, z: G2 O6 o1 W, k
  14. ; 0x20000000 这个也是根据上面的RAW的分区填写,
    " S9 x/ W- V& ^% v' I; {
  15. ;0x0000FC00 大小是 63Kb
    ; s7 d6 S$ n! U9 r
  16.   RW_IRAM1 0x20000000 0x0000FC00  {  ; RW data
    2 V: A/ L7 {: M+ U
  17.    ;段的存放位置使用默认的就可以了
    3 K3 K' p) _/ X
  18.    .ANY (+RW +ZI)
    5 G1 c. z8 g# [3 R; L0 j
  19.   }; ?3 r: O1 c1 W, x) l9 w6 D
  20. }0 R  l, V/ _1 d; G9 ]! r& f
复制代码

1 a6 z8 ~: o7 \/ E$ d; J8 g9 g+ H, ]: s, s) X
3.修改application的分散加载文件
修改如下,跟bootloader一样,就不啰嗦了
  1. ; *************************************************************5 q% J& D% @; R  U
  2. ; *** Scatter-Loading Description File generated by uVision ***& z4 w# X/ Y3 M0 ?) o! M0 a/ y, Y% \
  3. ; *************************************************************$ Z1 m0 v( k# Q( m5 a
  4. LR_IROM1 0x0800C000 0x00038000  {    ; load region size_region
    ( A; k& f" `5 {2 f: q
  5.   ER_IROM1 0x0800C000 0x00038000  {  ; load address = execution address- b/ Q, c2 M) l
  6.    *.o (RESET, +First)
    . |1 o" @2 J6 d" E
  7.    *(InRoot$Sections)7 C, r  \( W: X! W* G6 |6 @+ O- e$ N
  8.    .ANY (+RO)& j3 m5 i2 r% A3 O! v2 N
  9.   }6 i! R% h5 G6 P5 d$ V
  10.   RW_IRAM1 0x20000000 0x0000FC00  {  ; RW data    0x0000FC00' W4 J1 s% h0 a. O
  11.    .ANY (+RW +ZI)6 K7 N) t. C: H" A( g- R" \
  12.   }
    2 u4 g* I9 j, Y! _  [9 M3 n2 d. h
  13. }* B6 T0 Q3 z. _/ N5 p$ b: w2 v
复制代码
( V& \) q; R1 o$ i" T% F6 H

" n2 \7 g) p* n8 P, v4 G4.修改firmware的分散加载文件
*(InRoot$$Sections) 被注释掉了,因为 firmware 的程序是没有 __main 到 main 函数部分的代码的。下一章节写程序的时候会有讲解。其他的内容也跟bootloader文件差不多,上面的分区来写就可以了
  1. ; *************************************************************
    : ?1 ^) P/ i- a: O' \6 }) Y* E( ~
  2. ; *** Scatter-Loading Description File generated by uVision ***
    " `% O" E- U/ S1 @) M
  3. ; *************************************************************2 f4 l; e. i8 j  A4 p2 l6 I: l
  4. % \8 [0 ]0 A5 z/ A+ y4 k9 K( a9 J* a
  5. LR_IROM1 0x0807C000 0x00004000  {    ; load region size_region
    ; e( L8 w) s8 d) T' ^5 p+ m
  6.   ER_IROM1 0x0807C000 0x00004000  {  ; load address = execution address2 ?( W! I, v. B% ]
  7.    *.o (RESET, +First): Q5 X5 `+ k3 s
  8.    ;*(InRoot$Sections) 0 D3 k/ l5 N& ?
  9.    .ANY (+RO)
    9 I1 r2 A6 o& n7 V
  10.   }( S2 X: Z% r* e- _; t7 Q
  11.   RW_IRAM1 0x2000FC00 0x00000400  {  ; RW data  5 z9 @) O  T2 R  C# v
  12.    .ANY (+RW +ZI)1 |7 }5 u5 A5 g$ M% ]- z
  13.   }
    $ ]* X5 v9 M9 s; `7 R$ \, X
  14. }: _1 l2 O$ u- j, ?% m
复制代码
% p2 h1 n2 L  S0 C' {
& U- l+ v, e# d5 L* C, H
5. 注意事项
在MDK的默认设置里,链接的时候是不使用分散加载文件的 xxx.sct 文件。要使用 xxx.sct 文件需要将下面的设置去掉
LLK)B5}W)WA(Z28_DYZVX0H.png ( ~; Q( \5 V6 }8 x- H) T0 [
五、程序的下载设置
  • 由于本章还没实现IAP这部分的程序,所以 bootloader、application 和 firmware的程序都是使用烧写器来烧写到falsh的不同区域。所以需要设置一下。
  • 设置的地址跟大小也是根据上面的flash分区来设置的。
  • 主要设置MDK里面的 Debug -> Flash Download 的这两个地方,设置完这里就可以用Jlink将不同的程序烧写到不同的区域了。
  • 下图是 bootloader 的设置,其他两个也是根据实际来设置2 Z: h4 q3 h# ^4 A* G! N
    %IM8%5@HK}METIUD`XBCXXG.png % R/ U8 G; N6 \
六、实验现象
说了这么多先来个实验现象吧, 对于下面的程序分析和编写就下一章再写了。2 I' B9 J' `6 h) p) R, k
工程文件已经上传到码云---->
0 V* `" G# J0 k代码可能存在问题,有问题可以留言讨论。
  • hello bootloader 是在bootloader运行的时候打印出来的,打印完后就跳到应用程序执行了
  • num = 10和 num1 = 0 这两个值是通过函数指针调用firmware固件区的函数接口来获取的
  • 打印完上面的两个值之后循环打印hello app
    - g  F8 c$ k9 z( X1 X: J* Y现象如下图:6 x. K* H$ L6 @& x
    T6PYBAQPXKFJ3H`NS)G6C2H.png 4 [2 f) b3 C2 t7 J2 ]* c; X
- O! u/ Q: i7 [# ^! |# Q

: _" p# X+ ~# e! F
收藏 1 评论0 发布时间:2022-1-15 22:19

举报

0个回答

所属标签

相似分享

官网相关资源

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