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

STM32F072使用SD卡进行IAP升级  

[复制链接]
zhumx 发布时间:2017-9-15 17:31
本帖最后由 黑色裂变 于 2017-9-18 09:22 编辑

之前做的一个小项目,因为刚开始没有考虑到以后会经常升级,而每次升级都要旋开4颗螺丝拆壳,然后烧程序,再装壳,如果只要更新几个倒没啥感觉,但是一下更新几百个,那工作量。。。。,正好板子上有SD卡,就想着写个Bootloader程序,通过读取SD卡中的Bin文件进行IAP升级,这样可以大大简化以后的升级。IAP升级原理就不多说了,网上相关的资料和帖子一大堆,这里简单介绍我做的IAP方案,欢迎大家批评指正!
Bootloader程序设计
bootloader程序的设计思路很简单,流程图如下:


初始化程序就不介绍了,比较简单。主要介绍下Bin文件检测以及IAP过程。我将IAP过程分为5个步骤,如下:
Step1:检查是否存在升级文件,若存在,打开后跳至Step2,若不存在或者打开失败,跳至Step5
Step2:擦除App程序对应的扇区,擦除成功后跳至Step3,若擦除失败,跳至Step5
Step3:使用f_read()函数读取Bin文件,每次读取2048个字节,并写入Flash。当文件全部被写入flash后跳至Step4,若中间出现写入错误,跳至Step5
Step4:检查栈顶地址,跳转至App程序。若栈顶地址非法,跳至Step5
Step5:此步表示本次升级失败,死循环,同时LED提示升级失败,等待重新上电
查找升级文件时我固定从Update文件夹查找,所以只要将Bin文件拷贝至Update文件夹就行了。
五个步骤的转换是通过switch函数实现的。代码如下:
  1.         while(1)
  2.         {
  3.             switch(iap_step)
  4.             {
  5.                 /* Step1:检查是否存在升级文件 */
  6.                 case 1:
  7.                 {
  8.                     /* 查找升级文件 */
  9.                     result = f_findfirst(&dj, &fno, "0:/Update", "FDR_update*.bin");
  10.                     
  11.                     /* 存在升级文件 */
  12.                     if(result==FR_OK && fno.fname[0])
  13.                     {
  14.                         /* 获取文件名字符串 */
  15.                     #if _USE_LFN
  16.                         fn_str = *fno.lfname ? fno.lfname : fno.fname;
  17.                     #else
  18.                         fn_str = fno.fname;
  19.                     #endif
  20.                         /* 得到完整的文件名路径 */
  21.                         sprintf(fname_path,"/Update/%s",fn_str);   
  22.                         
  23.                         /* 打开升级文件 */
  24.                         result = f_open(&file_fdr,fname_path,FA_OPEN_EXISTING|FA_READ);
  25.                        
  26.                         if(result==FR_OK)
  27.                         {
  28.                             /* 打开成功,准备升级 */
  29.                             iap_step = 2;
  30.                         }
  31.                         else
  32.                         {
  33.                             /* 打开失败 */
  34.                             f_close(&file_fdr);
  35.                             f_closedir(&dj);
  36.                             iap_step = 5;
  37.                         }
  38.                         
  39.                     }
  40.                     else
  41.                     {
  42.                         
  43.                         /* 不存在升级文件,直接跳转 */
  44.                         f_closedir(&dj);
  45.                         iap_step = 4;
  46.                         
  47.                     }
  48.                     break;
  49.                 }
  50.                
  51.                 /* Step2:存在升级文件,先擦除扇区 */
  52.                 case 2:
  53.                 {
  54.                     FLASH_Unlock();
  55.                     res = IAP_FLASH_Erase(APPLICATION_ADDRESS);
  56.                     FLASH_Lock();
  57.                     if( res )
  58.                     {
  59.                         iap_step = 3;
  60.                     }
  61.                     else
  62.                     {
  63.                         f_close(&file_fdr);
  64.                         f_closedir(&dj);
  65.                         iap_step = 5;
  66.                     }
  67.                     break;
  68.                 }
  69.                
  70.                 /* Step3:扇区擦除成功,准备依次读取并写入 */
  71.                 case 3:
  72.                 {
  73.                     memset(appbuf,0xFF,2052);
  74.                     f_read(&file_fdr,appbuf,2048,&br);
  75.                     
  76.                     FLASH_Unlock();
  77.                     
  78.                     res = IAP_FLASH_Write((u32*)appbuf,(u16)ceil(br/4.0f));
  79.                     
  80.                     FLASH_Lock();
  81.                     
  82.                     Toggle_LED_AP();
  83.                     
  84.                     if(res == 0)
  85.                     {
  86.                         f_close(&file_fdr);
  87.                         f_closedir(&dj);
  88.                         iap_step = 5;
  89.                         
  90.                     }
  91.                     else
  92.                     {
  93.                         /* 文件读完了 */
  94.                         if(br<2048)
  95.                         {
  96.                             f_close(&file_fdr);
  97.                             f_closedir(&dj);
  98.                             f_unlink(fname_path);
  99.                             iap_step = 4;   
  100.                            
  101.                         }
  102.                         
  103.                     }
  104.                     break;
  105.                 }
  106.                
  107.                 /* Step4:跳转至App程序 */
  108.                 case 4:
  109.                 {  
  110.                     /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
  111.                     if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
  112.                     {
  113.                         /* Jump to user application */
  114.                         JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
  115.                         Jump_To_Application = (pFunction) JumpAddress;
  116.                         
  117.                         /* Initialize user application's Stack Pointer */
  118.                         __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
  119.                         
  120.                         /* Jump to application */
  121.                         Jump_To_Application();
  122.                     }
  123.                     else
  124.                     {
  125.                         iap_step = 5;
  126.                     }
  127.                     
  128.                     break;
  129.                 }
  130.                
  131.                 /* Step5:升级失败,等待重新上电 */
  132.                 case 5:
  133.                 {
  134.                     if(GetFreqFlag(FREQ_0_5HZ))
  135.                     {
  136.                         Toggle_LED_AP();
  137.                     }
  138.                     break;
  139.                 }
  140.                
  141.                 default:
  142.                 {
  143.                     iap_step = 1;
  144.                     break;
  145.                 }
  146.                
  147.                
  148.             }//iap step switch
  149.             
  150.         }//end of bootloader while(1)
复制代码
特别要注意形参uint16_t Datalength是指的字数,就是uint32_t类型变量的数量,而f_read读取的是字节数,要除以4进行转换,刚开始就是没有转换导致写的flash数据不正常,跳转后死机。
跳转程序也是参考的官方例程。我设置的App程序起始地址为:0x0800 A000

此外bootloader程序的IAR工程配置如图,flash地址范围:0x0800 0000 - 0x0800 9FFF,占用40K


App程序设计
1、App程序主要在原来的程序基础上修改flash起始和结束地址,以及中断向量偏移。Flash地址范围我设为:0x0800 A000 – 0x0801 FFFF,占用88K,IAR配置如下:






2、由于STM32F0没有像F1,F4那样的中断向量偏移寄存器,需要通过进行内存地址映射来实现,具体实现原理参见http://www.51hei.com/bbs/dpj-40938-1.html
所以在App程序main函数开始的地方加如下代码:(参考官方例程修改)

app设置

app设置

其实在官方例程中为 RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);这并没有打开系统配置时钟,应该改为RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);我也是看到网上其他帖子才发现并改正过来的,在这里感谢网友们的分享!
以上就是我做的STM32F0的IAP升级方案,实际测试感觉速度很快,可能我的App程序不大,50K左右,升级过程基本在3秒以内。




评分

参与人数 1 ST金币 +10 收起 理由
MrJiu + 10 很给力!

查看全部评分

收藏 9 评论17 发布时间:2017-9-15 17:31

举报

17个回答
zhumx 回答时间:2017-9-18 09:23:26
MrJiu 发表于 2017-9-16 09:23
不过,支持一个!!!

谢谢版主,发现少了一幅图,重新编辑上传了
zhumx 回答时间:2017-9-18 17:59:53
ts2000 发表于 2017-9-18 15:57
做过类似的,顶一下楼主~

谢谢
包子不 回答时间:2017-11-30 15:04:15
谢谢分享,很实用的教程。
yongjun 回答时间:2017-9-16 07:58:09
支持一下
MrJiu 回答时间:2017-9-16 09:23:03
不过,支持一个!!!
小小超 回答时间:2017-9-18 15:57:27
做过类似的,顶一下楼主~
epochal 回答时间:2017-9-18 20:40:54
谢谢分享!
搬砖工 回答时间:2017-9-20 15:00:10
谢谢分享
Lxiao 回答时间:2017-10-14 15:33:42

谢谢分享,支持一下!
网络孤客 回答时间:2017-10-15 13:48:05
谢谢分享,很实用的教程。
jamesliutao 回答时间:2017-10-17 14:04:45
zhao.zhao 回答时间:2017-10-24 11:10:07
谢谢分享
zhukm1988 回答时间:2017-11-9 09:57:46
谢谢分享,支持..
xmshao 回答时间:2017-11-9 17:29:03
谢谢分享!
anny 回答时间:2017-11-29 16:07:49
多谢分享
12下一页

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版