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

以STM8单片机为例,该如何实现Bootloader呢?

[复制链接]
gaosmile 发布时间:2020-10-22 23:05
这次出差是为了升级程序解决Bug,用户已经将产品封装起来,无法开盖,只能使用CAN总线来更新程序,用Bootloader实现。其实就是通过上位机把.bin/hex文件以CAN通讯的方式发送给单片机并存储在规定的Flash中。这个过程与手机端更新APP类似。
微信图片_20201022230345.jpg
& b, C# E  X, A+ o2 v& X+ O
以STM8单片机为例,该如何实现Bootloader呢?今天和大家分享一下。
01
) R! D" k( ]# z7 {4 T& S) H4 I
% o  B* t1 a, h& U# H1 l

6 j  y. E% _# ^9 e4 O. m* U! E2 Y! Z$ Z* _" y+ E
什么是Bootloader

- Q( `6 y+ g* P8 P* f
Bootloader是一段用于更新自身应用软件并独立运行的代码,常被用于升级产品和修复产品bug。STM8单片机如果要下载hex文件的话需要通过STVP和STLINK来实现,单片机的引脚SWIM就是下载接口。如果产品在用户端被封装好了,无法通过SWIM来下载该怎么办呢?就使用Bootloader,STM支持CAN和UART实现Bootloader。就是通过CAN通信或者UART通信将数据存放在STM8的Flash上。
02
0 @1 K, ]4 G  A) [# c
8 l$ `/ q4 Z+ ]3 h2 |
% C3 ]; r+ {1 l# }: o
& G3 i0 Y0 h5 Q! s7 ]/ p7 l$ z
划分Flash区间
+ U4 Q0 L0 F4 n
STM8的中断向量跳转地址是固定的,会跳转到0x8000对应中断的偏移地址,所以会把Bootloader存放在0x8000开始的空间内,比如给Bootloader代码所划分的空间为4k,那么空间起始地址为:0x8000-0x8FFF;那么应用代码的起始地址就可以从0x9000开始。
03

. g; [2 N1 u9 s# k+ R) E+ J
! m) W* N4 ~9 B6 Y2 W. V3 `- F# V, u8 _4 h, q. S5 \
% r# l& A7 ~+ c9 o# l0 B- x4 M+ K
修改中断向量表
) `0 V4 c. e- c3 [0 A
STM8的中断向量表通过一段特定的代码来实现,并需要根据前文提到的空间划分来修改。STM8的应用程序起始地址是0x8400,默认的向量表如下代码所示。
  1. 2 k1 ^: g' S3 w
  2. __root const long reintvec[]@".intvec"=
    / B# u, G0 J7 L) v% Z
  3. {
    # e; ~! k$ J# ]( W
  4. 0x82008080,0x82008404,0x82008408,0x8200840c,
    , ]# Y: {2 l. u( H2 [
  5. 0x82008410,0x82008414,0x82008418,0x8200841c,
    2 k/ c+ x2 y5 X- d8 t6 r& _! G! b
  6. 0x82008420,0x82008424,0x82008428,0x8200842c,
    # T. J) T% f0 o% g; A, B$ r
  7. 0x82008430,0x82008434,0x82008438,0x8200843c, & f9 X, y' L' S5 T# {8 D
  8. 0x82008440,0x82008444,0x82008448,0x8200844c, / V3 a8 }# n% \3 t% E; p# n& V
  9. 0x82008450,0x82008454,0x82008458,0x8200845c, # D! R1 w4 G$ m' V; a" ~
  10. 0x82008460,0x82008464,0x82008468,0x8200846c, " ?3 g9 |/ v) m0 g. J
  11. 0x82008470,0x82008474,0x82008478,0x8200847c, ! K9 z. r# \& [  l  {6 L& K
  12. };
复制代码
前文已经将应用程序的起始地址修改为0x9000,所以,向量表的的修改方法为:除了第一个元素为,其余的元素将8改为9,修改完后代码如下:
9 E2 O! V, Z6 a  a6 h; g- Y3 K
  1. % ]3 S2 J# A0 L7 D' Z/ D; @, Q; L% U+ ?
  2. __root const long reintvec[]@".intvec"=
    1 r! g# \: @& B) ^% P. Q) w
  3. {   
    ) b. O- [, K- G  ?! @) |9 L* n
  4. 0x82008080,0x82009404,0x82009408,0x8200940c,
    5 }2 z6 d2 j# p1 c
  5. 0x82009010,0x82009014,0x82009018,0x8200901c,9 C$ d3 G2 [" h' x0 b7 m# M) D
  6. 0x82009020,0x82009024,0x82009028,0x8200902c,: }+ q* {- I! ^$ r+ V( ^5 _1 ~/ [
  7. 0x82009030,0x82009034,0x82009038,0x8200903c,8 A! X. u. v7 c
  8. 0x82009040,0x82009044,0x82009048,0x8200904c,
    $ e( h- k" F$ J
  9. 0x82009050,0x82009054,0x82009058,0x8200905c,9 u: P0 L: K6 d& J
  10. 0x82009060,0x82009064,0x82009068,0x8200906c,5 v' J5 W0 ^/ `1 }5 y, A$ {
  11. 0x82009070,0x82009074,0x82009078,0x8200907c,% g& R! M. z; e* D. E- u
  12. };
复制代码
* [% R+ `! ^  C: L3 K9 k* b
04

0 u1 B7 m& J7 x( G1 {0 G
6 ]5 {. k9 Q3 T  J
+ C1 E1 _2 D: J
- l# @6 i4 D8 J# k: O) y* P
修改ICF文件
ICF文件存放在编程环境的安装目录下,每个型号/系列的单片机都会对应一个ICF文件,需要修改一下ICF文件,这里需要根据flash空间的划分来修改,前面将Bootloader的终止地址设置为0x9FFF,所以修改如下:
6 n7 v$ j* R' o9 A5 d7 g) `

  1. 4 @- m$ `4 y7 U) W2 ]+ k: Z; o9 a
  2. define region NearFuncCode = [from 0x8000 to 0x8FFF];  \9 i. T! r: Y" g) J2 ^
  3. define block INTVEC with size = 0x80 { ro section .intvec };- j1 s, O; {" Q  z5 I
  4. place at start of NearFuncCode  { block INTVEC };
复制代码
7 H& {* X4 |6 G2 o6 Y- Z
微信图片_20201022230348.jpg
05
7 g" B, _- j" m
$ g& k4 T7 W3 g; @9 y! _
" n6 g, |+ f' e

, T/ Y0 w8 A. Q" v: m1 m
跳转命令
所谓跳转,就是在应用程序中跳转到Boot中去升级;升级完成后需要跳转到应用程序中,所跳转的起始就是起始地址。Bootloader跳转到应用程序的代码如下,
0 Q: m0 C& Z% U7 p2 l9 e4 s) V

  1. 8 Z/ A( R4 H9 }) H
  2. asm("LDW X,  SP ");
    9 i9 g# H* h- c& G- g) t" [+ C
  3. asm("LD  A,  $FF");* C8 Y  l% e4 u$ w3 T+ k
  4. asm("LD  XL, A  ");9 s+ b: k( v! N6 q, N& B7 m" u/ O
  5. asm("LDW SP, X  ");
    ) O: ~) F$ h6 j& C7 l
  6. asm("JPF $9000");
复制代码
应用程序跳转到Bootloader中的代码如下
8 H9 `5 ~* V6 _

  1. / V- H5 k7 \- s4 f) Y3 W$ s. f
  2. sm("LDW X,  SP ");
    ( F9 o3 v1 B( [5 f& K, I
  3. asm("LD  A,  $FF");
    % n4 F' L& R- E+ P. G$ M, r. E
  4. asm("LD  XL, A  ");$ x9 V5 s8 h1 w. J+ W/ }
  5. asm("LDW SP, X  ");  J6 S$ w0 a, ~8 ^+ W
  6. asm("JPF $8000");
复制代码
7 p+ b- ?8 s, t8 L" E. m
06

2 z6 C! ]1 H1 M5 K8 m% k" G, y
, c  [! V3 [- w% U  h# ~$ a% b1 j$ y
8 i8 J" d" p# G& u5 b2 f* a, r
( e- A& l: T# N: ^5 f  v
编写交互代码
以上设置好之后,就可以编写交互代码了,所以交互代码其实就是一套协议,规定了应用程序如何跳转到Boot,在Boot中如何处理和存储数据,这需要上位机的支持。如果只是用于自家的产品,就可以自己定义协议。也可以使用标准的协议,比如汽车行业中的UDS(统一诊断服务)Bootloader实现之后,就可以使用CAN/UART来实现产品固件的升级了。这就是Bootloader的关键内容,本文你学会了吗?留言讨论一下吧。+ m" y2 `, M8 ?7 a6 y

4 Z; t; j0 b) K% b
收藏 评论2 发布时间:2020-10-22 23:05

举报

2个回答
懒人-75055 回答时间:2020-10-23 18:34:57
七八年前做过,但是忘了。用的是一个转码协议,也是用CAN进行文件传输升级
懒人-75055 回答时间:2020-10-23 18:45:23
这个不像是BootLoader升级,反而像在线编程。上电的时候一般都是跳转到BootLoader,如果无BootLoader代码,单片机再跳转到应用程序。在使用中升级和BootLoader升级是不太一样的,BootLoader升级,应用程序就不能跑了,而在应用升级是可以的,可以把升级文件先保存到备份的Flash再进行重启,这时BootLoader中运行Flash擦写,覆盖原来的应用程序就可以了。BootLoader升级应该是通过触发条件,转载新的中断向量后程序让运行指针跳转到BootLoader,然后BootLoader等待接收升级文件。两个操作都差不多。
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版