搜索
bottom↓
回复: 56

STM32 IAP升级成功,庆祝一下

  [复制链接]

出0入0汤圆

发表于 2015-7-31 14:51:22 | 显示全部楼层 |阅读模式
花了一天的时间才做好,真开心。
本来以为会很麻烦,原来麻烦的地方只是如何将APP传输到设备中。
写上位机软件就弄了半天,其它的IAP程序如何擦写如何跳转网上都有现成的例子,修修改改就能用。
具体的思路是把IAP程序和APP程序分成两个区域,IAP占ROM中的0x08000000-0x08002FFF,0x08003000之后的地址都归APP使用。APP的intvec设为0x08003000,ROM Start也需设为0x08003000。
因为我要做GPRS远程升级,下载APP的功能代码比较多,所以程序下载的协议就没放在IAP中了,直接用APP内原有的通讯协议来做。

下面放上IAP程序的代码,供有需要的朋友参考,部分代码抄自网上。
开发环境:IAR for ARM,使用STM32F103ZE。

需要注意的有几点:
1、SystemInit()函数会修改中断中断向量表偏移量,所以要修改中断向量表偏移量的话,NVIC_SetVectorTable函数要放在SystemInit的后面。
2、本例子中用到W25Q64作为存储区,所以如果要使用的话要自己选个片内地址或弄个外部存储器。修改读写函数Read_count和Page_Program即可。


  1. #include "stm32f10x.h"
  2. #include "w25q64.h"

  3. #define TRUE            0
  4. #define FALSE           1
  5. #define FLASH_PAGE_SIZE         2048    //FLASH页大小
  6. #define FLASH_PAGE_MAX          256     //FLASH页数量
  7. #define ApplicationAddress      0x08003000

  8. #define ADD_IAP         0x400000        //IAP数据起始地址
  9. #define ADD_IAP_FLAG    0x480000        //标志存放区
  10. #define IAP_UPDATA_FLAG 0x98123021      //升级标志

  11. typedef struct{
  12.     u32 flag;//标记
  13.     u32 add;//起始地址,以0开始
  14.     u32 len;//长度
  15.     u32 crc;//crc校验码
  16. }IapDef;

  17. typedef         void (*pFunction)(void);     
  18. pFunction       Jump_To_Application;
  19. uint32_t        JumpAddress;

  20. u8 buff[FLASH_PAGE_SIZE];

  21. u32 FlashErase()//擦除FLASH
  22. {
  23.     u32 i;
  24.     //擦除
  25.     for(i=0;i<(FLASH_PAGE_MAX-(ApplicationAddress&0xFFFFF)/FLASH_PAGE_SIZE);i++)
  26.     {
  27.         if(FLASH_ErasePage(ApplicationAddress+i*2048) != FLASH_COMPLETE)      //判断是否擦除成功
  28.             return FALSE;
  29.     }
  30.     return(TRUE);
  31. }
  32. u32 FlashWrite(u32 ADDR,u8 *buf,u32 len)//写入FLASH
  33. {
  34.     //写入:
  35.     u32 i;
  36.     unsigned short temp;            //临时数据
  37.     for(i=0;i<(len/2);i++)
  38.     {
  39.         temp = (buf[2*i+1]<<8) | buf[2*i];            //2个字节整合为1个半字
  40.         if(FLASH_ProgramHalfWord(ApplicationAddress+ADDR,temp) != FLASH_COMPLETE)      //判断是否写入成功
  41.         {
  42.             return(FALSE);
  43.         }
  44.         ADDR +=2;      //地址要加2,因为每次写入的是2个字节(1个半字)
  45.     }
  46.     return(TRUE);
  47. }
  48. IapDef LoadIap()//从W25中读取标记结构体
  49. {
  50.     IapDef      iap;
  51.     Read_count(ADD_IAP_FLAG,(u8 *)&iap,sizeof(IapDef));
  52.     return(iap);
  53. }
  54. u32 IapCrc(u32 add,u32 len)//计算并返回CRC值
  55. {
  56.     u32 crc,i;
  57.     u32 tmp_len;
  58.    
  59.     CRC_ResetDR();//复位CRC数据寄存器
  60.    
  61.     while(len)
  62.     {
  63.         if(FLASH_PAGE_SIZE<len)
  64.         {
  65.             tmp_len=FLASH_PAGE_SIZE;
  66.         }
  67.         else
  68.         {
  69.             tmp_len=len;
  70.         }
  71.         len-=tmp_len;
  72.         Read_count(ADD_IAP+add,buff,tmp_len);
  73.         
  74.         for(i=0;i<tmp_len;i++)
  75.         {
  76.             CRC->DR=buff[i];
  77.         }
  78.         add+=tmp_len;
  79.     }
  80.     crc=CRC_GetCRC();
  81.     return(crc);
  82. }
  83. void SaveIap(IapDef iap)//将标记结构体写入W25
  84. {
  85.     Sector_Erase(ADD_IAP_FLAG);//擦除W25Q64的扇区
  86.     Page_Program(ADD_IAP_FLAG,(u8 *)&iap,sizeof(IapDef));//将结构体写入W25Q64
  87. }
  88. int main()
  89. {
  90.     u32 len;
  91.     RCC_DeInit();
  92.     //NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0 );//重定向中断向量表
  93.     SystemInit();/* 配置系统时钟为72M */
  94.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );
  95.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE );
  96.     w25_int();
  97.    
  98.     IapDef iap,iap2;
  99.     iap=LoadIap();
  100.     iap2=iap;
  101.     if(iap.flag==IAP_UPDATA_FLAG)
  102.     {
  103.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC,ENABLE);//开启CRC模块时钟
  104.         if(iap.crc==IapCrc(iap.add,iap.len))//核对要升级数据的CRC校验码
  105.         {
  106.             //解锁
  107.             FLASH_Unlock();            //解锁Flash
  108.             FLASH_SetLatency(FLASH_Latency_2);            //因为系统时钟为72M所以要
  109.             
  110.             FlashErase();//擦除FLASH
  111.             
  112.             while(iap.len)
  113.             {
  114.                 if(iap.len>FLASH_PAGE_SIZE)
  115.                 {
  116.                     len=FLASH_PAGE_SIZE;
  117.                 }
  118.                 else
  119.                 {
  120.                     len=iap.len;
  121.                 }
  122.                 iap.len-=len;
  123.                 Read_count(ADD_IAP+iap.add,buff,len);
  124.                 FlashWrite(iap.add,buff,len);
  125.                 iap.add+=len;
  126.             }
  127.             //上锁:
  128.             FLASH_Lock();      //Flash 上锁,一个固件库函数即可实现。
  129.             
  130.             iap2.flag=0;
  131.             SaveIap(iap2);/*程序更新完毕后将IAP升级标志去除
  132.             之所以用iap2是为了保留add/len/crc的数据。
  133.             */
  134.         }
  135.     }
  136.    
  137.     //跳转
  138.     if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)      
  139.     {
  140.         JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);                  //
  141.         Jump_To_Application = (pFunction) JumpAddress;                              //
  142.         __set_MSP(*(__IO uint32_t*) ApplicationAddress);                             //
  143.         Jump_To_Application();         
  144.     }
  145.    
  146.     return 0;
  147. }
复制代码

出0入0汤圆

发表于 2015-7-31 14:59:20 | 显示全部楼层
谢谢分享,我也想弄,无耐上位机程序不会写.能否分享下上位机程序,和工程吗,谢谢

出0入0汤圆

发表于 2015-7-31 14:59:44 | 显示全部楼层
还没玩过IAP 但是看楼主的热情,还是支持一下。

出0入0汤圆

发表于 2015-7-31 15:16:31 | 显示全部楼层
我用的覆盖升级,所以稍微简单些。

出0入0汤圆

 楼主| 发表于 2015-7-31 15:18:31 | 显示全部楼层
mvip 发表于 2015-7-31 14:59
谢谢分享,我也想弄,无耐上位机程序不会写.能否分享下上位机程序,和工程吗,谢谢 ...

很抱歉,因为这是公司的产品,原有的东西太多了,IAP是后面才添加的,所以不方便直接给出上位机程序和APP工程。

只能提供点思路供参考下。
你可以分成两个部分来尝试实现IAP,1、想办法将APP程序保存到存储器中。2、将保存的APP程序覆盖掉原有的APP区域。
第1步就看你板子上有哪些可以传输数据的东西,有SD卡/U盘之类的支持就最方便了,如果仅有串口也可以,很多串口调试软件支持将文件直接分解成字节发送。你可以将APP工程输出为bin格式,然后用串口调试软件发送到板子上,当然需要自己做一点简单的协议,或者直接用串口通讯超时的方式来确定数据接收完毕。之后再将收到的数据进行校验并保存就可以。
第2步就简单了,在IAP程序中读出保存的程序,覆盖APP区域就行。可以参考我的IAP程序或网上找例子,看懂意思后多试几遍就能成了。

出0入0汤圆

发表于 2015-7-31 15:24:22 | 显示全部楼层
恭喜恭喜。

出0入0汤圆

发表于 2015-7-31 15:51:06 | 显示全部楼层
多谢分享。
IAP下载

出0入0汤圆

发表于 2015-7-31 15:56:58 | 显示全部楼层
这个功能确实挺好的    我们的产品就一直在用

出0入0汤圆

发表于 2016-3-23 15:51:55 | 显示全部楼层
dalarang 发表于 2015-7-31 15:18
很抱歉,因为这是公司的产品,原有的东西太多了,IAP是后面才添加的,所以不方便直接给出上位机程序和APP ...

请问下lz,如果没有外部存储器,然后RAM也蛮小,但是要求波特率比较高,这样就没办法采取你说的办法了,那怎么搞,我试过缓冲,但是貌似还是跟不上速度,究其原因,就是flash擦写速度太慢,占用太多时间。

出0入0汤圆

 楼主| 发表于 2016-3-23 16:06:49 | 显示全部楼层
Hearthbeats 发表于 2016-3-23 15:51
请问下lz,如果没有外部存储器,然后RAM也蛮小,但是要求波特率比较高,这样就没办法采取你说的办法了, ...

这个简单,我是全部接收完毕后才更新,你没有外部存储器的话,需要用边接收边更新的方式。
RAM小不是问题,并不是一次就要把全部的数据接收完才更新的。
自己在通讯协议上做好规范,收到一个数据包后写到对应位置,写好后反馈确认帧,上位机收到确认帧后再发下一包。

出0入0汤圆

发表于 2016-3-23 16:11:23 | 显示全部楼层
MARK STM32 IAP

出0入0汤圆

发表于 2016-3-23 16:38:13 | 显示全部楼层
dalarang 发表于 2016-3-23 16:06
这个简单,我是全部接收完毕后才更新,你没有外部存储器的话,需要用边接收边更新的方式。
RAM小不是问题 ...

首先我是用一般的串口助手来发送的,好像没有一帧一帧数据来发送的功能。如果我为了实现这个,又去写个上位机,就太麻烦了,其次就是我的bin文件,大概6K左右,RAM可用不到1K,您说的那种方式我懂。我还想过把bin文件给拆分来发送。思想应该是跟你一样的,但是我怎么实现这个,就是一帧一帧数据发送。需要配套上位机吧,否则我就只有把bin文件给拆了,感觉更麻烦。

出0入0汤圆

发表于 2016-3-23 17:14:37 | 显示全部楼层
谢谢楼主分享!!!

出110入12汤圆

发表于 2016-3-23 17:25:37 | 显示全部楼层
dalarang 发表于 2016-3-23 16:06
这个简单,我是全部接收完毕后才更新,你没有外部存储器的话,需要用边接收边更新的方式。
RAM小不是问题 ...

边接收边覆盖,没有理解,程序正在运行的时候被其他程序覆盖了,那正在运行的程序还不乱了?这方面不了解,见笑~

出0入0汤圆

 楼主| 发表于 2016-3-23 17:52:50 | 显示全部楼层
hall 发表于 2016-3-23 17:25
边接收边覆盖,没有理解,程序正在运行的时候被其他程序覆盖了,那正在运行的程序还不乱了?这方面不了解 ...

边收边覆盖是要在iap程序里做接收,不能在app中做的。

出110入12汤圆

发表于 2016-3-23 17:58:24 | 显示全部楼层
dalarang 发表于 2016-3-23 17:52
边收边覆盖是要在iap程序里做接收,不能在app中做的。

哈哈~ 了解了 谢谢

出0入0汤圆

 楼主| 发表于 2016-3-23 18:00:09 | 显示全部楼层
Hearthbeats 发表于 2016-3-23 16:38
首先我是用一般的串口助手来发送的,好像没有一帧一帧数据来发送的功能。如果我为了实现这个,又去写个上 ...

用串口调试程序发的话,估计也没做校验了。6k的文件没有校验且波特率较高,我认为是不合适的。
自己玩玩也就罢了,做产品不太妥当。
看起来还是绕不过上位机这个坎。

出0入0汤圆

发表于 2016-3-23 18:16:57 | 显示全部楼层
谢谢分享,可以分享工程文件吗?谢啦!

出0入0汤圆

发表于 2016-3-23 20:13:47 | 显示全部楼层
dalarang 发表于 2016-3-23 18:00
用串口调试程序发的话,估计也没做校验了。6k的文件没有校验且波特率较高,我认为是不合适的。
自己玩玩 ...

我现在是这么打算的,我还是用串口助手来做,。我把bin文件拆分成几份,然后做一个简单的协议,分几次发送,每次发送完成,再发送校验码,来确定bin文件是否无误,确认无误后,把文件写入flash,再发送请求到串口请求下一份数据。这样的话应该可以的,bin文件已经拆分了,只是还没找到工具对bin文件求校验,你们是怎么球校验的,有没有相应工具。、

出0入13汤圆

发表于 2016-3-24 08:53:42 来自手机 | 显示全部楼层
谢谢楼主分享

出0入0汤圆

发表于 2016-3-24 09:49:40 | 显示全部楼层
IAP最好是分3个区域,一个放bootloader,另外两个放app,这样才更安全,不然做不好有可能变砖

出0入0汤圆

发表于 2016-3-24 22:34:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2016-3-25 12:00:04 | 显示全部楼层
留名.  最近也在研究

出0入0汤圆

 楼主| 发表于 2016-3-26 10:39:56 | 显示全部楼层
Hearthbeats 发表于 2016-3-23 20:13
我现在是这么打算的,我还是用串口助手来做,。我把bin文件拆分成几份,然后做一个简单的协议,分几次发 ...

闲来无事写了个BIN文件发送的上位机,可以分包发送。没有做下位机测试,你拿去试试看。
通讯协议:
68        帧头
C        控制码
DATA        数据,仅数据发送帧有
CS        前面所有字节的和校验

数据发送帧:68,控制码01,四字节数据起始偏移量,四字节本帧发送的数据长度,数据,校验码
示例68 01 00 00 00 00 20 00 00 00 D8 B9 00 20 4D 70 01 08 65 61 01 08 67 61 01 08 73 61 01 08 75 61 01 08 77 61 01 08 00 00 00 00 3D
00 00 00 00 数据起始偏移量
20 00 00 00本帧发送的数据长度32字节
后面紧跟着32个字节的数据
最后的3D是前面所有数据的和校验。

通讯测试:68 02 6A        //用于测试通讯你连接
擦除命令:68 03 6B        //用于向下位机发送擦除指令,下位机收到后需擦除对应APP区域,等待写入
重启命令:68 04 6C        //下位机收到该数据帧后重启

以上所有数据帧,下位机收到后需返回一个确认帧,若在1秒内未返回确认帧则视为通讯超时。
发送时会将BIN文件拆包成指定大小,每次在数据发送帧中附上本次的起始偏移量与数据量,发送给下位机,待收到下位机返回的确认帧后继续发送下一包。若超时未收到就终止发送。

下位机反馈的确认帧: 68 00 68




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2016-3-26 10:43:03 | 显示全部楼层
好帖留名

出0入0汤圆

发表于 2016-3-26 11:24:34 | 显示全部楼层
dalarang 发表于 2016-3-26 10:39
闲来无事写了个BIN文件发送的上位机,可以分包发送。没有做下位机测试,你拿去试试看。
通讯协议:
68        帧 ...

谢了哈 大神,这个确实比较方便,我下来先看看。不过我之前的方法我已经测试成功了,相对来你这个来说,原理是一样的,不过就是我需要用winhex手动拆分bin,指定协议然后分批发送,我现在已经成功实现了,不过没有加校验,比较坑爹,因为不晓得如何直接对bin文件校验。你的我先借鉴下,只是我不会写上位机,不晓得你是用啥写的,上位机这块能否请教学习呢。哈哈

出0入0汤圆

发表于 2016-3-26 12:34:33 来自手机 | 显示全部楼层
STM32 IAP 技术好贴。

出0入0汤圆

发表于 2016-3-29 18:00:31 | 显示全部楼层
楼主你好,不知你有没有碰到从APP调到Bootload中断无法使用,或者跳转之后程序跑飞的情况呢?恳请指教。

出0入0汤圆

发表于 2016-4-29 11:21:49 | 显示全部楼层
恭喜楼主

出0入0汤圆

发表于 2016-9-14 08:53:30 | 显示全部楼层
本帖最后由 vjcmain 于 2016-9-14 08:55 编辑
dalarang 发表于 2016-3-26 10:39
闲来无事写了个BIN文件发送的上位机,可以分包发送。没有做下位机测试,你拿去试试看。
通讯协议:
68        帧 ...


谢谢提供的工具和思路,您的工具我试用了下,升级思路和软件做得非常棒,不过使用的过程中发现了一个bug,即第一帧数据和校验是正确的,但是第二帧开始往后的数据帧和校验是错误的:)  ,下位机我按照你上位机协议好了,可以往FLASH写数据了,但是由于后面软件发的教研帧错误,我都是抠出来手工算 然后用串口一帧一帧发的。好痛苦 .大神求助

出0入0汤圆

 楼主| 发表于 2016-9-14 10:24:28 | 显示全部楼层
vjcmain 发表于 2016-9-14 08:53
谢谢提供的工具和思路,您的工具我试用了下,升级思路和软件做得非常棒,不过使用的过程中发现了一个bug ...

因为这是产品中的一部分,为了不泄露公司代码,当时只把IAP部分单独提取出来做成一个软件,通讯协议也重新编了,自己就没有特地写个下位机测试。
下面这是修正了后续数据帧的校验码bug的,顺便连上位机源码也一起送了吧,VS2010 C#。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2016-9-14 10:51:40 | 显示全部楼层
本帖最后由 vjcmain 于 2016-9-14 10:52 编辑
dalarang 发表于 2016-9-14 10:24
因为这是产品中的一部分,为了不泄露公司代码,当时只把IAP部分单独提取出来做成一个软件,通讯协议也重 ...


好感动,谢谢大神,请问你在杭州吗?

出0入0汤圆

 楼主| 发表于 2016-9-14 10:58:01 | 显示全部楼层
vjcmain 发表于 2016-9-14 10:51
好感动,谢谢大神,请问你在杭州吗?

非大神

在温州地区

出0入0汤圆

发表于 2016-9-14 12:50:54 | 显示全部楼层
STM32 IAP升级  mark

出0入0汤圆

发表于 2016-9-14 22:32:50 | 显示全部楼层
dalarang 发表于 2016-9-14 10:58
非大神

在温州地区

谢谢提供修正BUG后的软件,使用你的软件,花了三个晚上我的IAP终于跑通了,再次感谢。

出0入0汤圆

发表于 2016-9-26 14:18:30 | 显示全部楼层
支特楼主的无私分享,感谢!

出0入0汤圆

发表于 2016-9-26 21:03:37 | 显示全部楼层
不错谢谢楼主

出0入0汤圆

发表于 2016-9-26 21:09:53 | 显示全部楼层
好东西,谢谢楼主分享哈

出0入0汤圆

发表于 2016-9-26 21:28:06 | 显示全部楼层
哇 值得祝贺一下

出0入0汤圆

发表于 2016-9-26 22:14:27 | 显示全部楼层
写flash的时候,如何开门狗刚好喂狗,容易写失败,不知各位有没有遇到

出0入0汤圆

发表于 2016-9-27 19:30:01 | 显示全部楼层
这个真的需要留个记号,IAP远程升级!

出0入0汤圆

发表于 2016-9-28 14:48:02 | 显示全部楼层

出0入0汤圆

发表于 2016-9-28 14:59:30 | 显示全部楼层
这个很好,程序出现BUG了不用再将仪器发回来写程序了。

出0入0汤圆

发表于 2016-9-28 14:59:54 | 显示全部楼层
这个很好,程序出现BUG了不用再将仪器发回来写程序了。

出0入0汤圆

发表于 2016-9-29 08:57:04 | 显示全部楼层
3050311118 发表于 2016-9-26 22:14
写flash的时候,如何开门狗刚好喂狗,容易写失败,不知各位有没有遇到

升级时更改看门狗设定时间 升级退出后改回来

出0入0汤圆

发表于 2016-10-28 10:57:45 | 显示全部楼层
楼主讲的比较清晰呀,很好

出0入0汤圆

发表于 2016-10-31 16:04:56 | 显示全部楼层
在研究,看看

出0入0汤圆

发表于 2016-10-31 21:23:16 | 显示全部楼层
好东西,正想学习下这个IAP,刚好看到此贴,感谢楼主的无私

出0入0汤圆

发表于 2017-7-17 10:22:53 | 显示全部楼层
感谢分享

出0入0汤圆

发表于 2017-7-18 09:29:40 | 显示全部楼层
是同一份代码分两次编译吗

出0入0汤圆

发表于 2017-7-18 10:08:56 | 显示全部楼层
我写了两个程序,应用程序用MD5校验,校验过了升级,不过直接等待,超时自动返回,稍微麻烦点

出0入0汤圆

发表于 2018-4-2 18:04:53 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2018-4-6 00:53:57 来自手机 | 显示全部楼层
厉害,最近在看相关的东西

出0入0汤圆

发表于 2018-6-29 16:09:08 | 显示全部楼层

STM32 IAP标记下~~

出0入0汤圆

发表于 2018-6-29 16:53:36 来自手机 | 显示全部楼层
挖坟能不能少一点

出0入53汤圆

发表于 2018-7-13 11:27:06 | 显示全部楼层
dalarang 发表于 2016-9-14 10:24
因为这是产品中的一部分,为了不泄露公司代码,当时只把IAP部分单独提取出来做成一个软件,通讯协议也重 ...

能推荐学习c#的书籍或者视频资料吗

出95入100汤圆

发表于 2018-7-13 15:41:21 | 显示全部楼层
上位机没搞过
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-11 10:49

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表