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

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

[复制链接]
STMCU小助手 发布时间:2022-1-15 22:19
章节说明
STM32 IAP固件升级实验分为一下的章节(加粗的字体是本章节的内容):
一、Flash和RAM的区域划分、工程建立、程序分散加载、程序烧写
二、Stm32 bootloader、application、firmware 程序的分析和编写
三、使用DMA收发串口的不定长数据
四、通信协议的设计
五、STM32 IAP程序的设计$ [5 S4 x; r: f; A  r
六、上位机的程序的编写
! M. z( x$ s/ R5 l% ]( m/ u! J9 [
一、Flash区域的划分1.区域划分
  • 实验使用的是 STM32F103VET6型号的MCU。这个单片机的型号的内部flash的大小是512Kb, RAM的大小是64Kb。
  • 因为一般使用的都是flash的启动方式(即flash 的起始地址0x0800 0000被映射到 0x0000 0000。STM32的启动方式可以查看《STM32中文参考手册》) 所以flash的区域划分如下:5 x  o* b) j3 W/ J7 ~
1627979-20200118160928915-2018591605.jpg 0 h; R" u; m5 T5 l
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" l5 W  \7 g) Y1 U7 e3 t) o
3. 每个分区作用
  • bootloader 启动加载程序,主要用来加载和启动应用程序,还有更新应用程序
  • parameters 主要用来记录信息,bootloader 和 application 的信息交互
  • application 应用程序区,主要用来实现所需要的业务的程序
  • update region 程序更新区,主要存放更新下载的程序,当然也可以直接下载到 application 区,但是如果更新失败了,应用程序就不能执行了。所以单独划分一块区域,存放更新下载的序,更新完后再覆盖到application然后复位运行
  • firmware 固件区,主要存放一些函数接口,用户可以通过函数指针直接调用。像tiny-4412、smart210、esp32等这些板子的芯片在irom里面都提供了一些函数接口,通过地址可以直接调用这些函数。/ D5 b& `- r6 }/ n: m: m* q( Z
二、RAM内存的划分
# ?7 e: _. ]+ h0 D! K, b# H1、区域划分
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这类堆内存管理函数。0 P. x0 R. D3 |* e4 {6 B) s
3、简单说明
  • 因为STM32的flash 是norflash 读的时候可以像内存一样读,但是写的时候不能像内存那样子写,所以这些 RW 段 ZI 段都是加载到内存里。加载到哪里,这是由分散加载文件.sct文件(和链接脚本一个意思)里面说明。至于怎么加载 ,stm32 函数库的start_up.s文件的__main 到 main函数的过程就是加载数据到RAM空间。后面再介绍.sct文件5 R( H* H" x1 T7 f" n
三、工程建立
工程中需要三个project,分别是 bootloader application firmware 如下图:
1627979-20200118161053289-1264155561.jpg % H# P0 W+ W+ Q8 z# ?4 b4 A5 l
四、分散加载
因为程序存放在不同的区域了,并且每段区域的程序是独立的,所以在链接每个程序的时候需要告诉连接器,程序怎么放,程序加载启动的时候又应该怎么加载,堆区和栈区的位置这些都要告诉链接器。我们可以通过分散加载文件.sct 文件来告诉链接器。下面来看一下这个文件
1.原来的分散加载文件6 F6 F8 d& i1 K8 h4 f5 r1 m4 D. }
  1. ; *************************************************************4 i) E$ f* r/ Z) z
  2. ; *** Scatter-Loading Description File generated by uVision ***, P* f$ H, F0 D& h4 J3 c
  3. ; *************************************************************& T. e1 o  ]5 J6 \& f7 N4 n, ?
  4. ;LR_IROM1 段名/域名4 N, q0 l+ J5 p! H) ?
  5. ;0x08000000 程序加载的起始地址& N, Z9 A: B: _* s! e2 }9 x
  6. ;0x00080000 加载域的大小8 I; [7 L6 E$ S
  7. LR_IROM1 0x08000000 0x00080000  {    ; load region size_region
    % f6 g6 t4 o: }; i/ y) v6 P
  8.   ;ER_IROM1 执行域的名称  
    4 W) b6 S% m* F
  9.   ;0x08000000 程序的执行起始地址+ Z$ r& s0 y5 @9 B# E
  10.   ;0x00080000 执行域的大小' O+ S4 @- X, t8 h. J7 R0 B2 I
  11.   ;一般程序是在 flash 里面运行的所以 程序的执行地址等于加载地址,如果想要让程序运行在RAM中,执行地址修改为RAM的地址
    4 b& h3 x9 z3 n
  12.   ER_IROM1 0x08000000 0x00080000  {  ; load address = execution address; C! N$ F8 e1 z! a  V8 {
  13.    ;下面就是指定某些段怎么链接了! ?7 Y- [) g# `# y
  14.    *.o (RESET, +First)   ;链接的时候最先存放的是 所有.o文件的RESET段,紧跟的是First段(RESET段在start_up.s文件中有定义)
    4 Y9 C1 G  `: I/ C
  15.    *(InRoot$Sections)   ;然后存放 __main 到 main的这段代码,这段代码主要是将flash的RW和ZI段加载到RAM中
    ( `1 l; h7 I* `$ u( B* z
  16.    .ANY (+RO)            ;紧跟着的是所有文件的只读数据(RO段),一般是向量表、代码段和常量(字符串常量,和const修饰的数据)
    * j: ~0 r9 [1 u3 n
  17.   }
    ' n% D0 u1 q+ ^2 u2 i# M5 j
  18. ;RW_IRAM1 可读可写数据的段名
    / n% y, Z# A3 i  F
  19. ;0x20000000起始地址  
    6 v& D. ?  g4 r; |6 ?) ?+ _  t) {
  20. ;0x00010000大小
    : w% s2 N( Q* a; I+ V" p8 k/ ^: ^
  21.   RW_IRAM1 0x20000000 0x00010000  {  ; RW data, ?/ n4 G% R( f  s( e3 [
  22.    .ANY (+RW +ZI);紧接着的是(RW段),(ZI)段1 X! [4 U1 b- Y2 B8 ]& S) J2 ]
  23.   }
    ) M9 n6 v5 \& J+ D( x
  24. }( p" N, h" ^& T. u$ N, L2 t4 N* J1 M, w3 @

  25. - a+ A$ O- G9 m1 P' Z7 H
复制代码

% K2 s: x3 H; N% c/ f
Region的名称可以自己定义或者修改,重要的是地址要分配对就可以了。" g9 a& K9 p0 m6 T( C0 ^: p
Heart_of_Eagle这位博主有一篇比较详细的博文值得参考,不过不是MDK的sct文件的,原理都是大同小异0 {  G' j/ h# j6 m
MDK也是有详细的帮助文档,不过是纯英文的,想用好sct可以阅读里面的内容/ s/ o2 ^" B: {+ Z+ Z4 y4 ~% ~' ^
1.
1627979-20200118161128852-617757783.png
1 i9 H0 }0 {: T( k, n5 K8 Z5 T: R  C& W! e( H
2.
1627979-20200118161146238-1228850186.png . z  g2 I) B: _4 d0 y9 f+ i. P: e
2.修改bootloader的分散加载文件
根据上面的flash和RAM的划分修改sct加载文件,如下代码块:
  1. ; *************************************************************8 h+ h2 a$ ^# O" @& N! k
  2. ; *** Scatter-Loading Description File generated by uVision ***! V# ^- V- K4 t% u" ]
  3. ; *************************************************************
    . \2 l; W% l+ ~
  4. ;因为bootloader是第一个启动的程序,而且机器上电复位的时候是从0x0800 0000开始执行(因为被映射到了0x0000 0000)地址6 t  \* i0 j, X7 I* ^& R, t
  5. ;所以bootloader加载域的起始地址和执行地址都是0x0800 0000" d7 Q* k' `8 V: |7 j
  6. ; 0x0000B800域的大小(46kb)也是通过上面的设计的分区来填写
    : x; x' l2 t8 [0 j" M7 `
  7. LR_IROM1 0x08000000 0x0000B800  {    ; load region size_region% o  n/ T+ P8 Z0 P5 A8 `5 L
  8.   ER_IROM1 0x08000000 0x0000B800  {  ; load address = execution address0 j- J' Q% x  {9 x
  9.    ;里面段的存放位置使用默认的就可以
    , n3 e; K& i& M
  10.    *.o (RESET, +First)
    ; G( t" f: }- F1 M" E
  11.    *(InRoot$Sections)) ~  ?4 B. E! |9 `( u
  12.    .ANY (+RO)
    $ k7 U, _' [: a$ z& a
  13.   }
    ) |! X$ C2 r  X8 F
  14. ; 0x20000000 这个也是根据上面的RAW的分区填写,
    ; r2 S- w9 c4 u" v& G" g
  15. ;0x0000FC00 大小是 63Kb
    ; |$ V$ g% |$ @+ y! X; A
  16.   RW_IRAM1 0x20000000 0x0000FC00  {  ; RW data
    * H5 W4 a2 H6 A
  17.    ;段的存放位置使用默认的就可以了1 i+ x. ^+ T$ X
  18.    .ANY (+RW +ZI)
    ; Q' C: Z; t: `6 o" G
  19.   }, x. f8 O8 [, n% n% e  Z0 U5 `. P4 [
  20. }! {7 P9 ]! E% T
复制代码

, ~/ b* [2 K7 h5 j5 r0 s9 I  ]" N6 T0 b+ q/ {6 l
3.修改application的分散加载文件
修改如下,跟bootloader一样,就不啰嗦了
  1. ; *************************************************************
    ( _" v  g- K8 x6 X7 |" y8 v
  2. ; *** Scatter-Loading Description File generated by uVision ***
    0 Y  u8 f7 T% v- j  M
  3. ; *************************************************************
    1 ^( }6 R6 y7 P/ i& S6 H
  4. LR_IROM1 0x0800C000 0x00038000  {    ; load region size_region" d  |1 `( b8 V! j: R$ B
  5.   ER_IROM1 0x0800C000 0x00038000  {  ; load address = execution address
    " K- {6 R( i( |; G! _
  6.    *.o (RESET, +First)
    ! _0 @# E0 x% J" J3 e  n, F2 F1 |
  7.    *(InRoot$Sections)
    & T" m& D2 s3 A
  8.    .ANY (+RO)% J3 m! @. Y/ ^7 T0 }
  9.   }7 ?$ p4 U; G9 F& a! m  A
  10.   RW_IRAM1 0x20000000 0x0000FC00  {  ; RW data    0x0000FC00. D6 Q$ F4 K: @7 }9 I4 T
  11.    .ANY (+RW +ZI)
    % I6 W  S" R! n* [; `2 _
  12.   }
    ! i# n6 l! P8 F; F" b
  13. }  D% g! r5 \  ^& S* L
复制代码

6 P& L% P3 b5 I" F; _6 P+ m( `+ N7 n8 }! U
4.修改firmware的分散加载文件
*(InRoot$$Sections) 被注释掉了,因为 firmware 的程序是没有 __main 到 main 函数部分的代码的。下一章节写程序的时候会有讲解。其他的内容也跟bootloader文件差不多,上面的分区来写就可以了
  1. ; *************************************************************
    . a9 h0 r3 q% g0 c* e  W. x
  2. ; *** Scatter-Loading Description File generated by uVision ***
    # K+ @# G+ s! q$ p! N+ W& V6 x3 L
  3. ; *************************************************************
    : `; ?5 ]1 V6 v6 Y. x; ~" P4 X

  4.   ]& ^1 C5 N9 K4 H+ s
  5. LR_IROM1 0x0807C000 0x00004000  {    ; load region size_region% g3 P( F% N) ^
  6.   ER_IROM1 0x0807C000 0x00004000  {  ; load address = execution address% s, \2 W% A4 Y0 n
  7.    *.o (RESET, +First)
    " h  _1 S6 d& ?6 j; ?) U1 D
  8.    ;*(InRoot$Sections)
    8 o1 D) a3 V, x# J0 Z1 d
  9.    .ANY (+RO)
    % h$ E3 l$ x/ u  l9 v3 J0 r' a. e
  10.   }/ _1 ?* ^4 C1 e& x8 D* w/ k
  11.   RW_IRAM1 0x2000FC00 0x00000400  {  ; RW data  
    " d( _' b" z6 q+ F, e
  12.    .ANY (+RW +ZI)
    / a- q- ?) ?; T/ S4 ?- Y6 ]2 }
  13.   }
    6 C- z7 k6 G4 f$ e3 [7 }
  14. }
    5 g- k( L$ N& Q" `4 y; V1 Z
复制代码

+ m4 p2 d& O+ R7 o/ }& M: V4 \0 H1 K; d5 L
5. 注意事项
在MDK的默认设置里,链接的时候是不使用分散加载文件的 xxx.sct 文件。要使用 xxx.sct 文件需要将下面的设置去掉
LLK)B5}W)WA(Z28_DYZVX0H.png ' i3 w' |! ~3 |! `) g
五、程序的下载设置
  • 由于本章还没实现IAP这部分的程序,所以 bootloader、application 和 firmware的程序都是使用烧写器来烧写到falsh的不同区域。所以需要设置一下。
  • 设置的地址跟大小也是根据上面的flash分区来设置的。
  • 主要设置MDK里面的 Debug -> Flash Download 的这两个地方,设置完这里就可以用Jlink将不同的程序烧写到不同的区域了。
  • 下图是 bootloader 的设置,其他两个也是根据实际来设置) B( L* G1 n+ h
    %IM8%5@HK}METIUD`XBCXXG.png 2 X# c4 v5 Y& ^" ~0 i
六、实验现象
说了这么多先来个实验现象吧, 对于下面的程序分析和编写就下一章再写了。
9 c9 @! ]- Y# V) {2 r/ o! u. e工程文件已经上传到码云---->
% I' o( t$ e/ v- N代码可能存在问题,有问题可以留言讨论。
  • hello bootloader 是在bootloader运行的时候打印出来的,打印完后就跳到应用程序执行了
  • num = 10和 num1 = 0 这两个值是通过函数指针调用firmware固件区的函数接口来获取的
  • 打印完上面的两个值之后循环打印hello app
    ( f8 c$ z8 v: ^7 y8 V2 r现象如下图:
    / h$ Q1 y" u! Z, k) t% v3 B T6PYBAQPXKFJ3H`NS)G6C2H.png
    % d+ m; @0 T% \; G. Y; B% \

% E' Y+ n* `. o% k1 o) {; O
: M+ v: f% A. i/ k( t5 T+ r) G$ L
收藏 1 评论0 发布时间:2022-1-15 22:19

举报

0个回答

所属标签

相似分享

官网相关资源

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