前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >STM32远程乒乓升级,升级流程源码详细说明

STM32远程乒乓升级,升级流程源码详细说明

作者头像
杨奉武
发布2019-11-10 23:10:56
1.9K0
发布2019-11-10 23:10:56
举报
文章被收录于专栏:知识分享知识分享

前言

  1.BootLoader程序,升级简要流程图

  2.其实主要的就是把程序文件写入环形队列,然后环形队列取出来数据写入Flash

  3.用户程序,简要流程图

细节说明

Flash调整(保持三份程序的stmflash文件一样即可)

一,Flash调整(可根据自己使用的f103系列的芯片进行设置),兼容f103全系列

  1.1 可在stmflash.h 调整Flash存储位置

  1.2 一般,用户只需要修改

  1.3 可在串口打印查看两份程序文件的配置信息

    user1ROMStart: 0x8004000 用户程序1 Flash存储的开始地址     user1ROMSize : 0x5c00 用户程序1 程序大小

    user2ROMStart: 0x8009c00 用户程序2 Flash存储的开始地址     user2ROMSize : 0x5c00 用户程序2 程序大小

  1.4 用户程序1配置

  1.5 用户程序2配置

程序升级前是先擦除

  1.如果获取的版本和当前版本不一致,擦除,获取另一份程序,允许数据写入Flash

  2.STM32的擦除函数

串口处理http数据部分

  1.程序太长不好截图,就粘贴出来

代码语言:javascript
复制
void USART1_IRQHandler(void)//串口1中断服务程序
{
    u8 Res;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        Res =USART_ReceiveData(USART1);    //读取接收到的数据
        
        Usart1ReadBuff[Usart1ReadCnt] = Res;    //接收的数据存入数组
        Usart1ReadCnt++;
        if(Usart1ReadCnt > Usart1ReadLen -10)//防止数组溢出
        {
            Usart1ReadCnt = 0;
        }
        Usart1IdleCnt = 0;
        
        
        if(HttpDataStartFlage)//下次来的是真实数据
        {
            if(IAPStructValue.PutDataFlage && (IAPStructValue.PutDataFlage^IAPStructValue.Overflow))//可以往环形队列里面写数据,同时没有溢出
            {
                if(PutData(&rb_tIAP,NULL,&Res,1) == -1)
                {
                    IAPStructValue.Overflow = 1;//环形队列溢出
                }
            }
        }
        
                //解析http数据-------------------------------Start
        //HTTP/1.1 200 OK
        if(!HttpHeadOK && IAPStructValue.PutDataFlage)
        {
            if(Res=='H' && HttpHeadCnt==0)HttpHeadCnt++;
            else if(Res=='T' && HttpHeadCnt==1)HttpHeadCnt++;
            else if(Res=='T' && HttpHeadCnt==2)HttpHeadCnt++;
            else if(Res=='P' && HttpHeadCnt==3)HttpHeadCnt++;
            else if(Res=='/' && HttpHeadCnt==4)HttpHeadCnt++;
            else if(Res=='1' && HttpHeadCnt==5)HttpHeadCnt++;
            else if(Res=='.' && HttpHeadCnt==6)HttpHeadCnt++;
            else if(Res=='1' && HttpHeadCnt==7)HttpHeadCnt++;
            else if(Res==' ' && HttpHeadCnt==8)HttpHeadCnt++;
            else if(Res=='2' && HttpHeadCnt==9)HttpHeadCnt++;
            else if(Res=='0' && HttpHeadCnt==10)HttpHeadCnt++;
            else if(Res=='0' && HttpHeadCnt==11)HttpHeadCnt++;
            else if(Res==' ' && HttpHeadCnt==12)HttpHeadCnt++;
            else if(Res=='O' && HttpHeadCnt==13)HttpHeadCnt++;
            else if(Res=='K' && HttpHeadCnt==14){HttpHeadOK = 1;HttpHeadCnt=0;HttpDataLength=0;}  
            else
            {
                HttpHeadCnt=0;
            }
        }
        
        
        #ifdef UserContentLength 
        //Content-Length: XXXXXXXX
        if(HttpHeadOK && !HttpDataLengthOK)//获取http发过来的数据个数
        {
            if(Res=='-' && HttpHeadCnt==0)     HttpHeadCnt++;
            else if(Res=='L' && HttpHeadCnt==1)HttpHeadCnt++;
            else if(Res=='e' && HttpHeadCnt==2)HttpHeadCnt++;
            else if(Res=='n' && HttpHeadCnt==3)HttpHeadCnt++;
            else if(Res=='g' && HttpHeadCnt==4)HttpHeadCnt++;
            else if(Res=='t' && HttpHeadCnt==5)HttpHeadCnt++;
            else if(Res=='h' && HttpHeadCnt==6)HttpHeadCnt++;
            else if(Res==':' && HttpHeadCnt==7)HttpHeadCnt++;
            else if(Res==' ' && HttpHeadCnt==8)HttpHeadCnt++;
            else if(HttpHeadCnt>=9 && HttpHeadCnt<=16 )//最大99999999个字节. 16:99999999  17:999999999 18:9999999999
            {
                if(Res!=0x0D)
                {
                    HttpDataLength = HttpDataLength*10 + Res - '0';
                    HttpHeadCnt++;
                }
                else
                {
                    HttpDataLengthOK = 1;
                    HttpHeadCnt = 0;
                }
            }
            else
            {
                HttpHeadCnt = 0;
            }
        }
        
        if(HttpHeadOK && HttpDataLengthOK && HttpDataLength && !HttpHeadEndOK)
        #else
        if(HttpHeadOK && !HttpHeadEndOK)
        #endif
        {//0D 0A 0D 0A
            if(Res==0x0D && HttpHeadCnt==0)HttpHeadCnt++;
            else if(Res==0x0A && HttpHeadCnt==1)HttpHeadCnt++;
            else if(Res==0x0D && HttpHeadCnt==2)HttpHeadCnt++;
            else if(Res==0x0A && HttpHeadCnt==3){HttpHeadEndOK = 1;}
            else HttpHeadCnt = 0;
        }
        
        if(HttpHeadEndOK == 1)//http数据的head已经过去,后面的是真实数据
        {
            HttpHeadEndOK=0;
            HttpHeadCnt = 0;
            HttpDataLengthOK=0;
            
            HttpDataStartFlage=1;
            
            Usart1IdleTime = 3000;//GPRS判断空闲时间需要3S左右,因为GPRS有延迟
        }
        //解析http数据-------------------------------end
        
        
    } 
} 

  2.处理程序主要就是去掉http数据的head,同时程序里面获取了总共的数据长度

  3.根据自己的服务器,选择是不是可以获取,获取的这个长度在写入Flash的时候使用了

把数据写入Flash部分

  1.写入的时候加了判断和限制

  2.写入Flash函数,为保证写入的正确,写入之后再读一下.

写入完成

  1.环形队列里面的数据写完了,同时空闲时间到了,然后判断有没有其他错误

  2.其实我以前在这里还有个判断写入Flash的数据 和 Web服务器返回的一致才可以

    后来改到了写入Flash里面,但是也不是判断的相等

  说下原因:

    在接收完程序数据以后,正常来讲,此时只等着串口空闲时间到,然后判断写入完成就好了

    其实此时网络模块不应该给单片机发送任何数据了

    但是呢!保证不了这段时间里网络模块不会往单片机再发一些数据!

    其实就是说,单片机已经写入完成了,但是有可能由于模块或者服务器的种种原因,可能还会追加多余的数据.

    有可能有人会说,把空闲时间设置的短一点不就好了,假设设置个 10ms

    首先,确实设置10ms基本上就解决了上面说的,但是

    GPRS特殊,本身GPRS数据延迟就有可能好几秒.....(更新的时候大家自己看数据,基本上一直有延迟)

    我已经设置了GPRS更新的时候空闲时间是3S

  综合考虑以后我才会

关于程序里面的两个定时器

一,下载超时定时器

  1.1下载程序的时候该定时器开始累加

  1.2.调用

  1.3.该定时器在写入Flash的时候清零

二,整体运行超时定时器

  1.该定时器只要执行BootLoader程序,就开始运行,除非是Wi-Fi配网的时候才会清零,是强制的.

  2.调用

用户程序

  1.获取上次更新的信息

  2.下面这个最好放到感觉程序没有问题了的地方

    比如:在后面的章节是程序连接上MQTT以后,才执行这个.然后把更新状态传给客户端

结语

我的程序看似写的相当复杂,但是只要理清思路其实也不是那么的难

只是有很多很多的细节,毕竟我要应对升级过程中的各种问题!

但是呢!这次的升级程序实际上很容易移植到其它单片机

F103系列的就不说了,只是改改Flash地址的事情

我呢后面会提供一节移植到F103RET6的教程

还有一节移植到 F407的教程

这次的代码整改下了很大功夫

我呢就是力求所有的代码要有很强的应用性.

第一:代码是写给别人看的

第二:代码更是写给别人用的

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-11-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 细节说明
  • Flash调整(保持三份程序的stmflash文件一样即可)
  • 程序升级前是先擦除
  • 串口处理http数据部分
  • 把数据写入Flash部分
  • 写入完成
  • 关于程序里面的两个定时器
  • 用户程序
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档