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

STM32F072使用SD卡进行IAP升级  

[复制链接]
黑色裂变 发布时间: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个回答
yon-gjun 回答时间:2017-9-16 07:58:09
支持一下
MrJiu 回答时间:2017-9-16 09:23:03
不过,支持一个!!!
黑色裂变 回答时间:2017-9-18 09:23:26
MrJiu 发表于 2017-9-16 09:23
不过,支持一个!!!

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

谢谢
epochal 回答时间:2017-9-18 20:40:54
谢谢分享!
细品黑夜 回答时间:2017-9-20 15:00:10
谢谢分享
Lxiao 回答时间:2017-10-14 15:33:42

谢谢分享,支持一下!
ldptest 回答时间:2017-10-15 13:48:05
谢谢分享,很实用的教程。
12下一页

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似分享

官网相关资源

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