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

基于STM32的IAP升级程序

[复制链接]
STMCU小助手 发布时间:2022-11-29 16:00
IAP介绍

IAP(In Application Programming)即在应用编程,IAP 是用户自己的程序在运行过程中对User Flash 的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。通常实现 IAP 功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信方式(如 USB、USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。这两部分项目代码都同时烧录在 User Flash 中,当芯片上电后,首先是第一个项目代码开始运行。
9 t9 G+ z& ^" f简单来说,就是程序首先运行在boot升级区,检测是否有升级程序,当有升级程序的时候,用户将升级的固件通过某种通信接口(如串口)传输到开发板的某个位置中,之后放在APP的位置。当没有升级程序,直接运行APP中的程序。


' L. Q( {. Z+ H6 Q3 G3 S+ ^* C

功能设计

将最新的产品固件通过串口上传到开发板中,按下按键1,开发板将固件更新到设置的功能程序存放地址,按下按键2,执行功能程序。

* V( A  z2 D& Y/ ~1 |) z0 z1 r

ISI[G)O{74{1HM`CSZ2Z4J1.png

8 P: Z" L9 Z) P  v4 h6 z# |

[BESNPJ7_JSB%O3NY(Z}]VV.png

$ O: B7 \( N& ^6 [% E1 @
硬件设计

使用的MCU为STM32F103! Z( ]5 }- p$ o1 C8 K4 G, P0 u3 |
使用元器件为两个按键和两个LED灯


; H( e; v1 t2 x- o

软件设计软件设计流程如下
  • 编写需要升级的产品功能程序
  • 设置产品功能程序在keil 5中Target的程序的Flash起始地址和大小,并且程序中设置中断向量表的偏移量
  • 生成产品功能程序的固件bin文件
  • 设置IAP升级程序存放的起始地址和大小
  • 串口接收产品功能程序
  • 将最新的升级程序放入到功能程序的Flash位置
  • 跳转到功能程序的Flash地址处
    : \4 g  R9 q, x
具体实现* G1 e3 `; ?9 }, i
设计功能程序

主要为两处:

  • 在main()函数中最开始处,添加
    ; H$ |9 t; i2 V7 N  ]3 ]

; ^7 J( D. x% @0 V( J/ x2 X4 r
  1. SCB->VTOR = FLASH_BASE|0x9C00;
复制代码
$ t! {  s6 s- d9 I; G# ^4 ~* e

2.在keil 5中Target的程序的Flash起始地址和大小

; u2 R) ]! \0 s" w3 O; i7 @, n

640 (1).png

  w, Z- i% }% j, @9 X

生成bin文件:我们通过在 MDK 点击 Options for Target→User 选项卡,在 After Build/Rebuild 栏,
. j6 I' k( T$ @; _勾选 Run #1,并写入:D:\32\Keil 5\ARM\ARMCC\bin\fromelf.exe --bin -o …\OBJ\LED.bin …\OBJ\LED.axf


' n( x% }: q' B4 p0 Y8 Q) Q

640.png

7 w" l8 v' r! P7 Z

编译后,就会生成.bin文件了。

2 y# @: }& G$ C

IAP实现程序
  • IAP写入程序
    , t5 I9 z7 w: Z; M! f: z将暂存在RAM中的程序存放到Flash的对应地址中
    1 o' o' ]9 z) R5 ]7 E9 Kappxaddr:应用程序的起始地址
    ( Z% O3 o5 X4 P6 F# c+ A% D6 zappbuf:应用程序CODE.1 P8 r) K3 o0 `( @! S3 a! Q
    appsize:应用程序大小(字节).
    1. void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)
      4 i2 C6 ^2 m& h, V' z# C
    2. {6 R6 h& v1 r* i9 O7 G
    3.   u16 t;9 d" V0 o( S, u) ~
    4.   u16 i=0;
      . v$ V: h$ X0 V7 d* |% f1 N
    5.   u16 temp;- n8 c. K* A$ T1 U  l2 i$ q# ^% E8 g
    6.   u32 fwaddr=appxaddr;//当前写入的地址. o, Z5 P2 c' a/ y7 k) L( G1 p
    7.   u8 *dfu=appbuf;
      & t6 P# r: o% O, t
    8.   for(t=0;t<appsize;t+=2)4 _' G- ^2 R- ~" f/ M- M8 X  [
    9.   {                * H- D- j9 w3 b
    10.     temp=(u16)dfu[1]<<8;0 n- C5 w' r) X" M
    11.     temp+=(u16)dfu[0];    : p2 I: i4 s: `* B4 r3 o( q
    12.     dfu+=2;//偏移2个字节1 }7 M- T( u1 z& |) h
    13.     iapbuf[i++]=temp;      
      * z0 W9 a+ v# p5 k# V! v/ b) D8 W, u
    14.     if(i==1024)4 |2 e1 ~! g9 }" k( z& _) ]( d& ?2 q
    15.     {
      6 v7 `3 L+ t8 W8 d  }0 w9 X
    16.       i=0;
      ! T' K! E# E; Z- G% H
    17.       STMFLASH_Write(fwaddr,iapbuf,1024);  
      3 z! r, F+ |4 i+ B/ l
    18.       fwaddr+=2048;//偏移2048  16=2*8.所以要乘以2.3 P: q9 h9 I; |, P- r# Y; |% L
    19.     }5 A- X4 Q2 ]1 y( M# L  e
    20.   }! S$ H6 `* H2 J
    21.   if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去.  * S0 Q  ^  \% b5 W+ S
    22. }
    复制代码
    * m9 e  |4 P# v( T
2.运行地址偏移程序& n! I! Y" G# K2 G
程序转移到指定地址运行
) W" s. Z. J' b/ ]" ]1 f- P跳转到应用程序段
0 ~2 w5 g! t" T+ I( \: Tappxaddr:用户代码起始地址.! S9 f* e7 S1 r" r/ S
  1. void iap_load_app(u32 appxaddr)+ T3 l- G( v" w4 ]$ ]) b7 z
  2. {
    ; f/ d. A) q! z9 L9 M
  3.   if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)  //检查栈顶地址是否合法.
    5 }' J. D6 F) q3 T: g+ Q% D
  4.   { , j" n& z* k: e  n- b" Z4 A. t
  5.     jump2app=(iapfun)*(vu32*)(appxaddr+4);    //用户代码区第二个字为程序开始地址(复位地址)   
    4 `* I9 @- {9 N1 \
  6.     MSR_MSP(*(vu32*)appxaddr);          //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
    - s& d5 |; K: x/ m6 t
  7.     jump2app();                  //跳转到APP.
    ' j3 g  y- r7 X5 H( N! t/ x  K
  8.   }# Z( j! E4 I( w( l& C+ G0 X- H
  9. }
复制代码

+ B  u$ g2 r9 R7 c0 O. \, U5 ]
& k4 e4 E7 w/ @
8 X; ~/ {% _& ]9 e$ S
主程序

通过按键对接收到的升级程序进行更新,或者直接转入到功能程序地址。

  1. while(1)! E& N0 |2 z; [) h; i) s
  2.   {
    1 g$ R5 i/ M& T+ K- E$ U
  3.      if(USART_RX_CNT)
    # a9 k6 P% {! R
  4.     {
    7 D( C, ~0 O" |4 A$ f
  5.       if(oldcount==USART_RX_CNT)7 F, w: \$ a/ R: t( y; U" ?7 s
  6.       {/ G2 j! }, A8 _% A
  7.         applenth=USART_RX_CNT;
    : Q; g0 q4 x- l( S
  8.         oldcount=0;
    6 U! h  g0 l2 i* \9 z1 X& ?
  9.         USART_RX_CNT=0;" u3 x0 h3 Q5 w0 V% I+ S2 g4 k
  10.         printf("代码长度:%dBytes\r\n",applenth);8 s! D  P8 v; R: w  ?& H
  11.       }else oldcount=USART_RX_CNT;      $ V/ z. F  Y3 g/ C  u
  12.     }8 b+ e2 _6 G# s8 a% [
  13.     if(key==WKUP_PRES)
    5 b' h. l3 M) ~/ S! E
  14.     {! b2 Y1 s6 P, }
  15.       if(applenth)
    7 M5 f9 S; d9 o3 z* R0 F/ e# N; ~
  16.       {
    8 Q  _* P+ n4 e2 w, ^
  17.         printf("开始更新固件...\r\n");  
    2 I( R8 q: s; x. u2 K9 O6 I
  18.          if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
    7 b6 }1 F, _5 K8 Y
  19.         {   6 l6 z" [5 V& @+ c) B1 X
  20.           iap_write_appbin(FLASH_APP2_ADDR,USART_RX_BUF,applenth);//更新FLASH代码
    4 T! \, e  i# G; ~' j
  21.           printf("固件更新完成!\r\n");  6 p, b5 \9 S; R  _" I+ {9 e6 ?
  22.         }else
    6 @0 _/ j0 Z2 E( _2 b0 {( M
  23.         {
    & O2 S: {* f$ T/ I, i! }( M7 p
  24.      printf("固件更新失败!\r\n");
      k8 S6 O7 @/ e2 ^8 s: `
  25.          
    * L1 `0 R' ~- Z
  26.         }
    ; d0 h' E0 h  Z/ l# a
  27.        }else
    + z2 o; {7 P- R8 q% u* |
  28.       {
    % Z- H8 L% q: L4 K# B! J
  29.         printf("没有可以更新的固件!\r\n");
    4 J' Z2 ^5 j1 p; i  `5 r4 U
  30.       }               
    * m* r7 a, ^2 e  N  ^" f
  31.     }   ~/ Y5 \6 `. c( G4 i
  32.     if(key==KEY1_PRES)
    . {  u$ I1 z( H* i+ L0 S
  33.     {: P. k/ |7 }9 z# @& |- R
  34.       printf("开始执行FLASH用户代码!!\r\n");
    % h* N+ ^1 j" [- `/ M
  35.       if(((*(vu32*)(FLASH_APP2_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
    $ t. @  `" F6 y9 ]+ d2 ]) X
  36.       {   & E& d$ _% ]4 ]) }& S" f  j0 X
  37.         iap_load_app(FLASH_APP2_ADDR);//执行FLASH APP代码. B$ g, f( A1 L- Y8 Z; ?
  38.       }else ' e) D3 A$ j! j) `: V: r; `
  39.       {1 E5 F# g% q. D; O  }7 R7 `, x4 T
  40.         printf("非FLASH应用程序,无法执行!\r\n");
    $ E3 N& V6 _  N0 k- b5 k0 h! {
  41.       }                  
    - ]3 |, d9 W$ I  h& j. x' H
  42.     }     . T5 ~3 O" Z+ O$ j7 V" b
  43.   }
复制代码

转载自: 跋扈洋

$ P. b1 ^" \+ _7 k* v' G
赞 收藏 评论0 发布时间:2022-11-29 16:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版