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

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

[复制链接]
gaosmile 发布时间:2020-10-22 23:05
这次出差是为了升级程序解决Bug,用户已经将产品封装起来,无法开盖,只能使用CAN总线来更新程序,用Bootloader实现。其实就是通过上位机把.bin/hex文件以CAN通讯的方式发送给单片机并存储在规定的Flash中。这个过程与手机端更新APP类似。
微信图片_20201022230345.jpg

4 W/ B  x( l8 S
以STM8单片机为例,该如何实现Bootloader呢?今天和大家分享一下。
01

" h  L+ X! E1 T8 k6 p2 U
% K8 K; ?$ s' F4 Y/ A1 w0 S! ]/ @5 @

: e3 |$ u/ Y  Q
什么是Bootloader

7 @& P- z/ v$ b8 f9 e+ b6 T
Bootloader是一段用于更新自身应用软件并独立运行的代码,常被用于升级产品和修复产品bug。STM8单片机如果要下载hex文件的话需要通过STVP和STLINK来实现,单片机的引脚SWIM就是下载接口。如果产品在用户端被封装好了,无法通过SWIM来下载该怎么办呢?就使用Bootloader,STM支持CAN和UART实现Bootloader。就是通过CAN通信或者UART通信将数据存放在STM8的Flash上。
02

$ }7 G+ C6 Z, o+ W1 @
0 g" v; `# ?2 q) E) f( k  [( D. Y% S* e% N* P' O/ _+ V
4 V9 u0 y3 B- i+ z
划分Flash区间

0 o" e4 j) l/ N4 s. D4 V5 Q6 F  B
STM8的中断向量跳转地址是固定的,会跳转到0x8000对应中断的偏移地址,所以会把Bootloader存放在0x8000开始的空间内,比如给Bootloader代码所划分的空间为4k,那么空间起始地址为:0x8000-0x8FFF;那么应用代码的起始地址就可以从0x9000开始。
03

7 @$ M8 w6 D1 M1 v8 l' K8 i+ Y* l, i* B; [3 p( M. y  R# R

2 |% u! @* ]! j7 L
! w7 g3 k+ U1 N+ \/ g& x
修改中断向量表
/ G* d% W& R  X2 e  m
STM8的中断向量表通过一段特定的代码来实现,并需要根据前文提到的空间划分来修改。STM8的应用程序起始地址是0x8400,默认的向量表如下代码所示。
  1. ' w+ F. e  e$ \7 D
  2. __root const long reintvec[]@".intvec"= - k0 |$ l4 h8 G  ]0 v4 s
  3. {  d* `8 a/ u6 G5 I
  4. 0x82008080,0x82008404,0x82008408,0x8200840c,
    : m) I0 P6 P. @: ?
  5. 0x82008410,0x82008414,0x82008418,0x8200841c, ( p) r6 f1 n9 V% I8 I- H, D
  6. 0x82008420,0x82008424,0x82008428,0x8200842c, % X4 V" C! y' Z; B7 \
  7. 0x82008430,0x82008434,0x82008438,0x8200843c, . K5 E$ |4 W0 Y/ E
  8. 0x82008440,0x82008444,0x82008448,0x8200844c, * N, G/ O) C# Z1 ^" W5 J( k
  9. 0x82008450,0x82008454,0x82008458,0x8200845c, 0 W  U4 j, n4 g9 ~6 Q5 N! |
  10. 0x82008460,0x82008464,0x82008468,0x8200846c, * W6 N1 ]/ r6 d+ G# g
  11. 0x82008470,0x82008474,0x82008478,0x8200847c, ) [" ?" V5 H$ b$ k0 ^$ @/ E
  12. };
复制代码
前文已经将应用程序的起始地址修改为0x9000,所以,向量表的的修改方法为:除了第一个元素为,其余的元素将8改为9,修改完后代码如下:; r% I- k; A" |9 ~& i9 ?, N
  1. ( d8 X! ?1 b6 w( @, }# ~) W
  2. __root const long reintvec[]@".intvec"=3 e$ `6 R/ W6 h: K0 |
  3. {   
    ; j% w$ D. @5 X
  4. 0x82008080,0x82009404,0x82009408,0x8200940c,
    # K, R$ @/ e- g: q& U' W
  5. 0x82009010,0x82009014,0x82009018,0x8200901c,
    ( }' ~* K( I) h" ?- W1 v
  6. 0x82009020,0x82009024,0x82009028,0x8200902c,! f2 g; L0 V6 B2 ^7 t. z3 |
  7. 0x82009030,0x82009034,0x82009038,0x8200903c,0 U9 j. F+ _7 b4 Q8 f
  8. 0x82009040,0x82009044,0x82009048,0x8200904c,/ w) W9 |- m% K( F3 G) q& A: h7 B
  9. 0x82009050,0x82009054,0x82009058,0x8200905c,$ U& E& ~% \& H& H  a2 C
  10. 0x82009060,0x82009064,0x82009068,0x8200906c,
    ) T1 H4 g9 x, e8 X5 D: M: g' r
  11. 0x82009070,0x82009074,0x82009078,0x8200907c,
    ; T" p: G2 v7 y% |2 F
  12. };
复制代码

; Q+ U8 R2 z, V  d, V
04

  _6 M- a2 [3 e- s! X) q' L
) U4 e! v. c5 z+ V* N; [
+ Q) p3 s' q+ W) p& g1 V& b( I+ r; \. W; E( n! r
修改ICF文件
ICF文件存放在编程环境的安装目录下,每个型号/系列的单片机都会对应一个ICF文件,需要修改一下ICF文件,这里需要根据flash空间的划分来修改,前面将Bootloader的终止地址设置为0x9FFF,所以修改如下:
1 K5 H8 Q9 k  ~

  1. , M3 {8 k% W5 G9 B" l+ q
  2. define region NearFuncCode = [from 0x8000 to 0x8FFF];' W2 \7 O$ N0 Q4 t& L
  3. define block INTVEC with size = 0x80 { ro section .intvec };$ m( R) m8 h8 \( n  T+ N
  4. place at start of NearFuncCode  { block INTVEC };
复制代码

- D$ w% w: ~! Y' ]7 c
微信图片_20201022230348.jpg
05

5 Z. {  B: r' q5 b$ M4 h( L6 |9 @2 b
; Z# i, x0 m6 W" U

6 \8 C) N* X7 u% Z# k3 O0 H- V# O
跳转命令
所谓跳转,就是在应用程序中跳转到Boot中去升级;升级完成后需要跳转到应用程序中,所跳转的起始就是起始地址。Bootloader跳转到应用程序的代码如下,9 ^8 m$ F$ a, s6 S6 G. q' x0 R% S1 X3 c

  1. % k' L7 U$ M( \. F4 p
  2. asm("LDW X,  SP ");6 x: h9 U' p+ S7 u( B, \) v4 l
  3. asm("LD  A,  $FF");
    2 _4 f, H5 j" F  }) K6 p$ Y. D- }
  4. asm("LD  XL, A  ");
    $ x3 H' a/ z3 [7 R
  5. asm("LDW SP, X  ");2 }/ H" D9 d/ E. K& N1 b
  6. asm("JPF $9000");
复制代码
应用程序跳转到Bootloader中的代码如下  l: z& E+ b5 v  N" ]4 V& w) H
  1. , f- z( M$ C2 |; a
  2. sm("LDW X,  SP ");% u' `+ m  N2 c+ Q! B* T7 v; R
  3. asm("LD  A,  $FF");
    ( W: M; W; E# f% v% X, i: }
  4. asm("LD  XL, A  ");) |5 d3 S. @3 q
  5. asm("LDW SP, X  ");2 E2 b# z) c$ o& x
  6. asm("JPF $8000");
复制代码

" z0 S) f+ F1 N) c: ^
06
$ Q) ^( s7 m$ {. O3 r( x) `

8 J8 J0 `) z: M2 N# v8 H" y$ F) P. L! e; C6 }$ }

( ]$ w  a& G- V- l
编写交互代码
以上设置好之后,就可以编写交互代码了,所以交互代码其实就是一套协议,规定了应用程序如何跳转到Boot,在Boot中如何处理和存储数据,这需要上位机的支持。如果只是用于自家的产品,就可以自己定义协议。也可以使用标准的协议,比如汽车行业中的UDS(统一诊断服务)。Bootloader实现之后,就可以使用CAN/UART来实现产品固件的升级了。这就是Bootloader的关键内容,本文你学会了吗?留言讨论一下吧。. }2 x3 T: L- P9 l
+ X9 W: \% |4 Q
赞 收藏 评论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管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版