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

STM32远程升级(基于串口本地升级与WiFi通信远程升级)  

[复制链接]
Y-D 发布时间:2017-6-9 10:45
/***************************************************
! {9 x" ?& m4 U+ D3 k*注意要想二次升级必须要在用户APP中将 UPDATA_FLAG[0]='0'并保存在flash中
2 i; o  ^5 B. o# }* C$ }5 G8 g8 j*设置完成后将单片机重启,重启完成将升级包通过串口发送给单片机即可升级完成
3 I. W5 k& M2 C4 T4 H*同时注意用户APP中需要在程序的开头添加SCB->VTOR = FLASH_BASE | 0x10000;语句2 O0 k8 N  R! h: q, A9 J; j, _
*本实验程序为考虑后期利用8266升级所以设置波特率为 115200) f4 {+ Z+ a! R$ p( L- ]
*注意本程序代码的升级包限定最小20个字节才为升级包否则为控制命令
  k% E& b+ o+ l+ v5 u****************************************************/3 H) a2 K, }8 a# h; R# V  T2 r. I4 J1 P
//主函数部分
- ?2 \+ z" q' j4 A: E( N$ I+ a#include "led.h"
* m5 k1 \) q" c9 r) E#include "delay.h"5 ]) s$ F7 X9 i5 N
#include "sys.h"
# `! C  {9 t1 [% J; Q#include "usart.h"0 h9 D( j7 f5 F4 A1 i
#include "stmflash.h"+ D( V7 W8 J$ m; V# x1 w
#include "iap.h"1 ]# K0 p9 g, b. f' K8 g
#include "time.h"
% f2 G+ w0 j: |  H. }# y  |u16  UPDATA_FLAG[1];4 E9 E  q7 O: x; b3 ^* Q  T1 R
int main(void). H! K5 G; H7 k9 p
{               
1 G* u0 A3 c0 {  t        u16 oldcount=0;                                //老的串口接收数据值
; U) s; Q; G& |8 t6 Z# \        u16 applenth=0;                                //接收到的app代码长度
& x6 c# |" `# z4 r; e8 H        static u8 START_UPDATA=0;* K! E1 [! y5 s& {
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
6 P2 f$ }5 Q4 S- o# L        uart_init(256000);        //串口初始化为256000: V4 u3 |$ s9 S% R- W  `7 s
        delay_init();                            //延时初始化 * f5 l+ L& L( c. s/ t
        LED_Init();+ U1 w% s% a) t2 A/ Y  p# p# B7 M* h
        TIM2_Init(9,7199);  //升级延时定时器
$ ]  _1 i$ Y: d3 U$ a- N        STMFLASH_Read(0X08071000,(u16*)UPDATA_FLAG,1); //读取更新标志   如果此标志位为:'1'代表程序已经更新了 如果为 '0'代表程序在执行IAP等待接收升级包
% K* c, B3 B' e& G        if(UPDATA_FLAG[0]=='0')4 Q  _7 @+ O/ A% g
        {8 w8 Q9 e4 _2 I6 L# g5 y: y
                //等待发送更新包,说明程序从用户程序进行了重启
- D) ?8 O& l4 u                //提示发送更新包
4 [+ w4 Z  d% v                printf("Please send update package....\r\n");* `: G3 v8 w, [; X; L/ G; p% d- w
        }
, P1 Q( ^3 Q! t- s" ^8 g        else if(UPDATA_FLAG[0]=='1')- n& G; ~7 r9 @  _9 M
        {
7 e8 Q0 h) T9 Z3 y4 S                printf("Loading...\r\n");, j# y7 D9 ?! z, a( D+ R, ?9 o% S
        }
+ w' j1 o9 e- d( T9 D3 A        while(1)
% f7 Y* Z; D; E! e3 }) M. q        {8 m- ~, f' [* w3 z& o
                LED1=!LED1;  //LED闪烁指示
# n. F( `; l: Q! k) X                delay_ms(100);
( A0 r% L9 F3 O  b9 t' l7 }1 W* w2 P                 if(USART_RX_CNT)
& G  Y5 D* Q2 i2 b& S                {
5 H& d4 L8 X! i( Z$ g8 S: g                        if(oldcount==USART_RX_CNT)//新周期内,没有收到任何数据,认为本次数据接收完成.: b+ }: O( Z; L4 S
                        {/ _/ f( v3 p. M  @2 Q
                                applenth=USART_RX_CNT;
& M. b/ H- T1 W3 C: L5 }% I                                oldcount=0;& h  N7 S" j0 |
                                USART_RX_CNT=0;. [) j9 M) f/ B$ `8 ]4 Z0 L  O
                                if(applenth>20) //此处强行规定发过来的升级包必须大于20个字节否则不予升级
0 O( l; f8 H. ^7 a6 v                                {* O6 ~3 N, j0 O" L
                                        printf("USER  CODE  RXC\r\n");  //提示升级包接收完成, |1 ]7 y8 f* ]' O- H; o9 l
                                        printf("CODE  SIZE:%dBytes\r\n",applenth);4 _% j  X3 i& F5 P* U
                                        START_UPDATA=1; //此标志为1时可以进入升级" e" M4 O! Y6 R( `9 g+ }+ s
                                        UP_DATA_Time_3000ms=0;
& I" q" ?. M- _( o0 c1 l! q                                }. C# \7 n. v( c3 Z
                        }else oldcount=USART_RX_CNT;                        * d5 [" p9 H4 ?: o
                }9 y  ^& r3 Y' b+ d: J
                if(START_UPDATA==1&&UP_DATA_Time_3000ms>=3000). ?. P" K9 T, w' s
                {
$ S1 ]) D) z* V$ _+ B- Y% f                        UP_DATA_Time_3000ms=0;9 ~' I% h! c8 A
                        START_UPDATA=2;& s" J# P2 H3 A  e+ S
                }
& {$ x7 I( U2 e8 z  a                if(START_UPDATA==2)! o& D1 g) _! w. ~; @
                {5 R3 d( L4 y2 a9 q
                        if(applenth)
: u' V; a$ Q% ]8 ?/ O                        {. v4 V# t$ {7 u) X* V6 t
                                printf("Start  updating...\r\n");        7 q/ f# |4 Y% h6 ~
                                if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
2 a1 I/ X% c) B                                {         , |8 T5 c2 Z  D$ R' K4 Q( X( E
                                        UPDATA_FLAG[0]='1';6 P5 s& A9 v3 n2 L& \7 t
                                        STMFLASH_Write(0X08071000,(u16*)UPDATA_FLAG,1);  //允许更新标志" b8 u- B* z+ }  C, ~. }$ B
                                        STMFLASH_Read(0X08071000,(u16*)UPDATA_FLAG,1); //读取更新标志
$ D7 O+ ]$ o+ g/ u8 u6 ~5 G                                        iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);//更新FLASH代码   ; H6 n/ I5 m: \9 v$ S7 B
                                        printf("Updated  firmware\r\n");        / ]$ _0 I  |( Z
                                        printf("Resart  \r\n");
+ b8 y2 y4 u; X- \0 V9 K( \) }! o                                        delay_ms(100);                //延时一小会儿等待上一帧数据发送完成  B& z; Y0 _4 P) _
                                        //软件重启CPU& t. P$ s3 u( f5 g3 e, d+ [
                                        __disable_fault_irq();
% u- F1 s% y/ _( T' m                                        NVIC_SystemReset();
# Y% I% ^- z: x' g7 U                                }
9 ?. k6 ^2 L; e$ G4 z                                else
! W% {% U* C2 @% r$ ^/ i                                {   
- W. g5 U0 L* m' N) j                                        printf("Illegal  Code!\r\n");% L& u3 S) v; Z/ ~  D
                                }
/ z) `1 ]7 r2 ^$ A( p; U                         }9 v: Q0 x* L: A2 q6 A) }
                        START_UPDATA=0;                                        . h( p! F; @9 Q5 Y1 K
                }9 U2 _5 f( {. d+ u" l
/**********************************************************************- m* \0 b  N1 w6 C, C
*有升级包进行升级- T6 B. t# a* T* I% @3 ?, p9 [
*此处的标志位需要在用户APP中进行清零后才可进行下一次的更新否则每次上电都会直接跳转到用户APP执行
% I, Q8 v  C+ U9 V6 f( b2 Q***********************************************************************/       
. }+ C' T& c0 p- X# e* E                if(UPDATA_FLAG[0]=='1')2 M; c6 Y/ C, t, l* x
                {
- c0 ]* r. m3 J1 o$ e" a0 H. {2 S                        if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.  此处测试一下是否会多次跳入0 {2 N* Z4 |, O7 Q
                        {       
( b7 Q7 b. `3 R* C5 s                                iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码3 f& y( K/ z1 N; I
                        }
9 d$ e* F2 Y  j) H! `0 ]8 c9 i5 ~                }
/ |- E4 B: m0 P8 P/ I        }              % M. M; ^' d- L8 Q
}4 t) f: o9 S) C( f

. c; i! `2 x. w//API部分
3 v. ?2 b2 C9 B! R/ D#include "sys.h"1 Q$ S2 D4 x, ?7 h) ~
#include "delay.h"
+ a- @) O+ b5 n8 g# S" m) x#include "usart.h"
6 A9 k1 r0 F6 U5 [4 v#include "stmflash.h"
( F# k- }. R# d- i; ?# ^9 a" }* x3 ?#include "iap.h"- ]) d3 I, Q: d0 M
iapfun jump2app; 7 B8 Y* \4 H" |0 p. F! v' r0 y
u16 iapbuf[1024];   
+ V2 ?9 j7 P, a) `# _2 y6 U//appxaddr:应用程序的起始地址
* N3 v! Z3 X+ ]/ p- A//appbuf:应用程序CODE., @6 |; a5 L2 a; E6 ^
//appsize:应用程序大小(字节).
2 E4 u) B  p9 ?4 d0 n9 C  Kvoid iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)
2 m3 M5 R- K0 S5 \0 i* l{
( P3 b5 _, ^, g; n) f        u16 t;
# V; q. a+ G- c9 z3 E! e5 b& n' s  }        u16 i=0;1 N: B( P5 T+ J0 Z0 ]0 x7 o
        u16 temp;% a$ m% W/ i# z7 V8 Z" V
        u32 fwaddr=appxaddr;//当前写入的地址( x+ Y  X$ b0 A7 o9 a$ T
        u8 *dfu=appbuf;+ j) W5 e2 g/ p. C$ C0 y
        for(t=0;t<appsize;t+=2)
* g2 {& _9 @/ {! ]3 F1 n" O        {                                                    
" [  C+ _3 m6 I9 r: ^                temp=(u16)dfu[1]<<8;0 A+ _5 {9 s1 g6 `
                temp+=(u16)dfu[0];          " |$ [$ m/ M% S- O$ d
                dfu+=2;//偏移2个字节& T! O9 ]$ r3 f5 B5 C8 j$ r& \
                iapbuf[i++]=temp;            % t/ w6 b% z0 F* ^
                if(i==1024)
  u0 ]* V3 f0 r                {
/ m  z( ]0 |( U9 A2 q/ p                        i=0;
) j, J' E1 w, e; O                        STMFLASH_Write(fwaddr,iapbuf,1024);       
" O5 t5 U1 y( b% K; v                        fwaddr+=2048;//偏移2048  16=2*8.所以要乘以2.
3 o8 I* f" l$ s9 h8 [                }. F8 m8 L. m/ i) c: t6 e
        }2 L0 E& p; O" j8 e  C7 [% `, o2 [. F
        if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去.  
9 K0 D+ O$ ?/ D$ z}5 R0 |5 v9 S* o7 I
//跳转到应用程序段6 n+ n5 L3 W0 k6 i: O& _
//appxaddr:用户代码起始地址.
. u% A1 s- u, j$ P" o, T, N# \8 `void iap_load_app(u32 appxaddr)
4 P- L0 w% \( Y0 U{  B( c0 C2 I* w) d" X. M) a& \
        if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)        //检查栈顶地址是否合法.- l6 V. o" G# x1 C% f  i0 |) P# f9 l
        {
& w3 Y& r+ A. }+ e                jump2app=(iapfun)*(vu32*)(appxaddr+4);                //用户代码区第二个字为程序开始地址(复位地址)                ) f/ _% Q) N5 [/ R0 s* N* s
                MSR_MSP(*(vu32*)appxaddr);                                        //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)8 n, F+ i' z# r2 s
                jump2app();                                                                        //跳转到APP.
, |5 @8 }, x* ^3 W8 |        }
0 ]+ |) e+ C8 e& j% v5 B: t}               
( K$ x9 |! `! I+ M* P
9 f, P6 x! G2 Y( t3 y

配套上位机.rar

下载

897.98 KB, 下载次数: 1126

本地升级和远程升级上位机

评分

参与人数 2 ST金币 +4 收起 理由
yyawl -1 很给力!
MrJiu + 5 很给力!

查看全部评分

赞 1 收藏 11 评论36 发布时间:2017-6-9 10:45

举报

36个回答
kylongmu 回答时间:2018-5-21 13:20:13
可以把wifi改为蓝牙串口模块,用手机app扫蓝牙来升级,为了安全最好用RSA验证一下身份。升级文件传输可以用ymodem协议。
wkc20180808 回答时间:2019-11-5 15:34:53
通俗易懂,可以在此基础上加上xmoder 的协议  ,保证了传输的可靠性,安全性。
mojiaxia 回答时间:2018-5-21 09:58:13
楼主你好,能否把这个参考单片机例程发给我参考一下,我的油箱是103572498@qq.com
zhao.zhao 回答时间:2017-6-10 11:49:06
谢谢楼主
MrJiu 回答时间:2017-6-10 13:56:23
要是能更加详细以及有一套完整的帖子,那就更好啦!!!!!!
Y-D 回答时间:2017-6-15 10:43:09
后面有时间了在更新的详细些。
zero99 回答时间:2017-6-26 13:18:49
学习了
huaiqiao 回答时间:2017-6-30 11:47:17
多谢楼主分享。, J* |! d; `$ _7 B2 T
! p- p- ~, Z0 Y% }( b
问下楼主,wifi模块是用esp8266吗?
A.K. 回答时间:2017-7-3 16:36:13
谢谢楼主的分享
/ a: S3 d( @, o1 i/ q
cpu-340177 回答时间:2017-7-18 09:53:29
' ^6 M/ C$ Y: S4 R1 j+ M
谢谢楼主的分享
1 X9 }& ]" ?6 t8 O& g% N2 L
奔跑的蜗牛321 回答时间:2017-10-10 10:12:29
能否把单片机程序也上传一下
zhao.zhao 回答时间:2017-11-27 10:42:42
谢谢
a838899 回答时间:2017-12-11 11:10:15
这个厉害啊 不错啊
西点钟灵毓秀 回答时间:2018-2-5 15:58:42
不错,这样可以空中升级了
zkevin8879 回答时间:2018-3-12 10:13:20
谢谢楼主了,这几天正在想这事呢
琦子 回答时间:2018-3-12 10:25:26
好文章啊 支持一下
大陶 回答时间:2018-3-12 11:14:49
学习了 谢谢楼主
123下一页

所属标签

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