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

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

[复制链接]
STMCU小助手 发布时间:2022-1-15 22:19
章节说明
STM32 IAP固件升级实验分为一下的章节(加粗的字体是本章节的内容):
一、Flash和RAM的区域划分、工程建立、程序分散加载、程序烧写
二、Stm32 bootloader、application、firmware 程序的分析和编写
三、使用DMA收发串口的不定长数据
四、通信协议的设计
五、STM32 IAP程序的设计0 @9 c. x8 T& W  G
六、上位机的程序的编写+ F: m! A, k% U( ^7 W* u

, W: e1 T- L5 @# o" `
一、Flash区域的划分1.区域划分
  • 实验使用的是 STM32F103VET6型号的MCU。这个单片机的型号的内部flash的大小是512Kb, RAM的大小是64Kb。
  • 因为一般使用的都是flash的启动方式(即flash 的起始地址0x0800 0000被映射到 0x0000 0000。STM32的启动方式可以查看《STM32中文参考手册》) 所以flash的区域划分如下:) i: I7 `2 M7 O6 a! x
1627979-20200118160928915-2018591605.jpg : Q7 `  j# U/ E* ]/ h, U
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
    $ p+ d% S6 W4 {! H5 C0 n) [5 H* X
3. 每个分区作用
  • bootloader 启动加载程序,主要用来加载和启动应用程序,还有更新应用程序
  • parameters 主要用来记录信息,bootloader 和 application 的信息交互
  • application 应用程序区,主要用来实现所需要的业务的程序
  • update region 程序更新区,主要存放更新下载的程序,当然也可以直接下载到 application 区,但是如果更新失败了,应用程序就不能执行了。所以单独划分一块区域,存放更新下载的序,更新完后再覆盖到application然后复位运行
  • firmware 固件区,主要存放一些函数接口,用户可以通过函数指针直接调用。像tiny-4412、smart210、esp32等这些板子的芯片在irom里面都提供了一些函数接口,通过地址可以直接调用这些函数。
    . `" H7 ~) B  M! d
二、RAM内存的划分: h" {8 a5 g. O' f0 u* A9 H
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这类堆内存管理函数。
    ; K% D& G# v" m+ S9 j7 x) ^2 t- k
3、简单说明
  • 因为STM32的flash 是norflash 读的时候可以像内存一样读,但是写的时候不能像内存那样子写,所以这些 RW 段 ZI 段都是加载到内存里。加载到哪里,这是由分散加载文件.sct文件(和链接脚本一个意思)里面说明。至于怎么加载 ,stm32 函数库的start_up.s文件的__main 到 main函数的过程就是加载数据到RAM空间。后面再介绍.sct文件# s: R' i6 [/ T' N3 Z7 G% D
三、工程建立
工程中需要三个project,分别是 bootloader application firmware 如下图:
1627979-20200118161053289-1264155561.jpg 9 v2 B7 [, w! Y# D6 K* I, }
四、分散加载
因为程序存放在不同的区域了,并且每段区域的程序是独立的,所以在链接每个程序的时候需要告诉连接器,程序怎么放,程序加载启动的时候又应该怎么加载,堆区和栈区的位置这些都要告诉链接器。我们可以通过分散加载文件.sct 文件来告诉链接器。下面来看一下这个文件
1.原来的分散加载文件9 e9 |- B& T  |  m3 D$ v
  1. ; *************************************************************
    ) Q8 R( |* [6 ~' L( G5 K1 _
  2. ; *** Scatter-Loading Description File generated by uVision ***( n9 ^( i) R1 n$ D
  3. ; *************************************************************
    $ h: W* [) P+ d9 ~# s
  4. ;LR_IROM1 段名/域名
    ' H, d7 m% t0 c. ~- S
  5. ;0x08000000 程序加载的起始地址) S: W8 I0 }% w" q
  6. ;0x00080000 加载域的大小
    + c4 J. @" R* m: _+ t. Z4 d
  7. LR_IROM1 0x08000000 0x00080000  {    ; load region size_region# w! v9 h  x: C
  8.   ;ER_IROM1 执行域的名称  . ~3 |* q$ ?: `  R5 B: Z; W& [/ W
  9.   ;0x08000000 程序的执行起始地址! m% s: z: H3 u1 p0 k
  10.   ;0x00080000 执行域的大小
    , g- c: Y" x% D- H
  11.   ;一般程序是在 flash 里面运行的所以 程序的执行地址等于加载地址,如果想要让程序运行在RAM中,执行地址修改为RAM的地址8 l  r  L9 K% x
  12.   ER_IROM1 0x08000000 0x00080000  {  ; load address = execution address! D( F" e1 t( g
  13.    ;下面就是指定某些段怎么链接了* D9 ?& q: t$ ~' O' A/ s: b2 [- T: K
  14.    *.o (RESET, +First)   ;链接的时候最先存放的是 所有.o文件的RESET段,紧跟的是First段(RESET段在start_up.s文件中有定义)
    1 E2 L1 Q' S% _. n2 u) w- V
  15.    *(InRoot$Sections)   ;然后存放 __main 到 main的这段代码,这段代码主要是将flash的RW和ZI段加载到RAM中2 V; Z5 C2 d9 j: i1 `8 v8 J
  16.    .ANY (+RO)            ;紧跟着的是所有文件的只读数据(RO段),一般是向量表、代码段和常量(字符串常量,和const修饰的数据): c, S* T& Q# i; D
  17.   }
    ! A$ P3 g9 `  J6 q
  18. ;RW_IRAM1 可读可写数据的段名2 M. }# ]9 h* o  t: v
  19. ;0x20000000起始地址  : s) O, C) k/ V7 C9 M7 \
  20. ;0x00010000大小
    : |' s+ z" W* R/ M0 i' D
  21.   RW_IRAM1 0x20000000 0x00010000  {  ; RW data) U) x3 n5 W; `' Z
  22.    .ANY (+RW +ZI);紧接着的是(RW段),(ZI)段
    . y8 K/ W8 J' b1 q8 ?
  23.   }$ Q* t; {: G* f6 [9 u1 s
  24. }
    : x( S/ `  x5 L) p& u' f" g

  25. ; K$ j5 N4 U0 H/ n$ A5 @
复制代码

6 P8 y/ x/ B% [, d8 \
Region的名称可以自己定义或者修改,重要的是地址要分配对就可以了。' f; D7 v- P& O9 ?' k! f; u
Heart_of_Eagle这位博主有一篇比较详细的博文值得参考,不过不是MDK的sct文件的,原理都是大同小异8 D: S( Y! X! c! F" n
MDK也是有详细的帮助文档,不过是纯英文的,想用好sct可以阅读里面的内容2 g% F+ r: G1 t% d# V% n4 F5 h6 F
1.
1627979-20200118161128852-617757783.png 6 V9 P+ P5 Q, [" z3 E! J: S
5 q6 Y( F. J+ P. \, H) T
2.
1627979-20200118161146238-1228850186.png
0 B5 b9 ^6 u6 D. J5 z
2.修改bootloader的分散加载文件
根据上面的flash和RAM的划分修改sct加载文件,如下代码块:
  1. ; *************************************************************4 m1 V4 \; S4 H
  2. ; *** Scatter-Loading Description File generated by uVision ***, ^8 @, X  }' t. W$ C
  3. ; *************************************************************
    2 x0 k& c- P2 q
  4. ;因为bootloader是第一个启动的程序,而且机器上电复位的时候是从0x0800 0000开始执行(因为被映射到了0x0000 0000)地址
    7 |2 u8 @5 `3 W/ S
  5. ;所以bootloader加载域的起始地址和执行地址都是0x0800 00000 F% \" V$ i1 V! a$ [1 F- t
  6. ; 0x0000B800域的大小(46kb)也是通过上面的设计的分区来填写# D; s. |: d, S: r. l0 c
  7. LR_IROM1 0x08000000 0x0000B800  {    ; load region size_region. q& {1 Z5 j9 x2 r( Z1 `" R4 P
  8.   ER_IROM1 0x08000000 0x0000B800  {  ; load address = execution address8 W/ {( k. F2 b( K8 n+ f4 t8 d9 m
  9.    ;里面段的存放位置使用默认的就可以
    4 k5 T& w' Y, ~$ r* J. t/ I9 N
  10.    *.o (RESET, +First)
    $ Z% G7 i2 q( j. f
  11.    *(InRoot$Sections), q6 K8 y1 D0 W
  12.    .ANY (+RO)  P4 H  s- z* J0 w' G
  13.   }
    / g, v4 b7 J& h! e
  14. ; 0x20000000 这个也是根据上面的RAW的分区填写,
    ' Y- ]! \8 E8 Z* l% R& r% o& a% A
  15. ;0x0000FC00 大小是 63Kb. {  j6 k: r/ h& f" C, e8 G+ p- W
  16.   RW_IRAM1 0x20000000 0x0000FC00  {  ; RW data
    * V, }( B. A7 d" b4 H' y
  17.    ;段的存放位置使用默认的就可以了! l3 T1 a- i% `& K
  18.    .ANY (+RW +ZI)
    & u! j3 h2 Q( ^3 f# b. _
  19.   }# P4 ~3 e2 C) H7 L+ w5 n2 ^& a- M
  20. }
    ) j- ~+ f( X8 Z. v( L
复制代码

; k' h; q) O9 ~3 a$ S% j" c6 {& W: q
3.修改application的分散加载文件
修改如下,跟bootloader一样,就不啰嗦了
  1. ; *************************************************************
    8 Q2 {$ W2 \2 J9 N: G
  2. ; *** Scatter-Loading Description File generated by uVision ***' ^% L" G2 ]: `$ u; ^
  3. ; *************************************************************
    ( }6 b; _) ]* z$ e) O4 x* l- C9 |
  4. LR_IROM1 0x0800C000 0x00038000  {    ; load region size_region) L/ s3 K. j" I: s4 u, e
  5.   ER_IROM1 0x0800C000 0x00038000  {  ; load address = execution address
    ) f( t) e& P' ~7 X4 I9 ~
  6.    *.o (RESET, +First)" @& Y$ S3 N: D( Y1 ?8 l8 f
  7.    *(InRoot$Sections)
    4 _4 r( g6 D4 T
  8.    .ANY (+RO)
    " p( p" `2 h1 C' ]1 K& P
  9.   }
    ' L2 h+ ^8 k5 |* j* v+ R! ^
  10.   RW_IRAM1 0x20000000 0x0000FC00  {  ; RW data    0x0000FC00
    7 K+ y. M3 j' D
  11.    .ANY (+RW +ZI)& x( J; K: v+ r+ Y0 q
  12.   }( p- y7 t6 ]4 {. s7 g
  13. }
      x3 w! c  B- n$ c% h
复制代码
* J4 C2 m- I% y/ j4 |# K: n3 y% _6 `
6 a9 [/ J. B' f, r- p! [
4.修改firmware的分散加载文件
*(InRoot$$Sections) 被注释掉了,因为 firmware 的程序是没有 __main 到 main 函数部分的代码的。下一章节写程序的时候会有讲解。其他的内容也跟bootloader文件差不多,上面的分区来写就可以了
  1. ; *************************************************************/ @( o$ x7 [0 O5 q0 R, r0 g1 ]
  2. ; *** Scatter-Loading Description File generated by uVision ***& H  h6 r( {" G6 h
  3. ; *************************************************************: l- y! z9 N7 {9 L/ O. H, z

  4. 8 c' z# S! t( l5 ~8 s" G1 L
  5. LR_IROM1 0x0807C000 0x00004000  {    ; load region size_region$ @' i3 H$ l' V0 R
  6.   ER_IROM1 0x0807C000 0x00004000  {  ; load address = execution address* h% v0 X) z9 O. k5 D- I! S
  7.    *.o (RESET, +First)
    ; h6 H4 C8 I+ B6 E6 |7 K
  8.    ;*(InRoot$Sections) ' v. D1 z* q/ i: P9 z
  9.    .ANY (+RO)# S7 D& q# ~5 d! l1 o, Q) O
  10.   }: K' Z. I& c( p
  11.   RW_IRAM1 0x2000FC00 0x00000400  {  ; RW data  
    ! I  U8 X9 E: e* K! p6 y
  12.    .ANY (+RW +ZI)
    ! j. A9 u# z/ e/ H
  13.   }
    . e; Z- L: d% ?9 T2 n6 U: Z
  14. }
    6 C% B/ C' `2 d+ T- t
复制代码
. a; o6 W- n  L9 t& I
5 J* O1 m: ~7 Y+ m; U0 i
5. 注意事项
在MDK的默认设置里,链接的时候是不使用分散加载文件的 xxx.sct 文件。要使用 xxx.sct 文件需要将下面的设置去掉
LLK)B5}W)WA(Z28_DYZVX0H.png
, p, G1 ~/ O( T+ X9 e6 ~! n  z
五、程序的下载设置
  • 由于本章还没实现IAP这部分的程序,所以 bootloader、application 和 firmware的程序都是使用烧写器来烧写到falsh的不同区域。所以需要设置一下。
  • 设置的地址跟大小也是根据上面的flash分区来设置的。
  • 主要设置MDK里面的 Debug -> Flash Download 的这两个地方,设置完这里就可以用Jlink将不同的程序烧写到不同的区域了。
  • 下图是 bootloader 的设置,其他两个也是根据实际来设置
    " X7 ^1 f' B! ]) K6 w %IM8%5@HK}METIUD`XBCXXG.png
    / ]- S  N! |$ S0 Y& m
六、实验现象
说了这么多先来个实验现象吧, 对于下面的程序分析和编写就下一章再写了。7 K$ v: b$ q# ]* \; W
工程文件已经上传到码云---->1 X' ?2 @' w1 a  |2 M4 U
代码可能存在问题,有问题可以留言讨论。
  • hello bootloader 是在bootloader运行的时候打印出来的,打印完后就跳到应用程序执行了
  • num = 10和 num1 = 0 这两个值是通过函数指针调用firmware固件区的函数接口来获取的
  • 打印完上面的两个值之后循环打印hello app
    3 f4 B+ w$ d- B9 z' _( |现象如下图:
    5 n; v  t* a- n# v+ F! \ T6PYBAQPXKFJ3H`NS)G6C2H.png
    * |: ]  n' `+ o( _5 W) R

8 g) W" {3 Q! ~! c! q! ^4 G# |+ r' S  z4 b4 }- r9 r
收藏 1 评论0 发布时间:2022-1-15 22:19

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版