AT32U盘IAP升级

前言

最近项目里做了一个U盘升级的需求,用雅特力的例程进行了些许更改,在这里记录分享一下。

原理

这里原理不赘述了,大家可以直接去官网上下载应用笔记和例程:
下载AN0030

U盘IAP升级的大致思路就是满足升级条件后,读取bin,然后写入flash再进行跳转。

具体操作

项目用的是AT32F423,flash有128K,我把前32K用来放IAP,后96K放APP(两个工程),在KEIL上分开下载(APP程序下载不是必须的),如下所示:
IAP
APP

APP的bin文件可以通过KEIL生成:
在这里插入图片描述

fromelf.exe --bin -o “@L.bin” “#L”

注意英文输入法

将IAP先烧进单片机,把APP的bin文件放进U盘,进入IAP后将U盘插上即可完成升级。

更改部分

读取bin函数

例程里给find_upgradebin函数是读取文件名确定gbin_list[bin_id].BaseAddr,我在使用过程中出现了读取错误的问题
在这里插入图片描述

而且对文件名有限制,我这改了一下:

uint8_t find_upgradebin(char *path)
{
  FRESULT res;
  FILINFO fno;
  DIR dir;
  char *fn;
  char *po = NULL;
  
  res = f_opendir(&dir, path);
  if(res == FR_OK)
	{
    while(bin_id == 0) 
    {
      res = f_readdir(&dir, &fno);
      if(res != FR_OK || fno.fname[0] == 0)
      {
        break;
      }
      if(fno.fname[0] == '.')
      {
        continue;
      }
      fn = fno.fname;
			
      if((po = strchr(fn, '.')) != NULL)
      {
				/*find upgrade bin*/
        if((!memcmp(po + 1 , "BIN", 3) || !memcmp(po+1, "bin", 3)))
        {
          gbin_list.BaseAddr = FLASH_APP_START_ADDR;
          gbin_list.Filesize = fno.fsize;
          memcpy(gbin_list.BinName, fno.fname, 256);
          bin_id ++;
        }
      }
    }
  }
  f_closedir(&dir);
  if(bin_id == 0)
    return BIN_FAILED;
  else
    return BIN_OK;
}
#define IAP_USE_FLASH_SIZE    (32*1024)  //32K
#define FLASH_APP_START_ADDR        0x08008000

使用的时候bin文件名不要太长就行。
在这里插入图片描述

跳转函数

#define SET_MSP(dwValue) __ASM volatile ("msr msp, "#dwValue)
void (*pfTarget)(void);

void IAP_Jump(uint32_t dwAddr)
{
   uint32_t dwStkPtr, dwJumpAddr;
   uint32_t i = 0;
   dwStkPtr = *(UINT32 *)dwAddr;
   dwJumpAddr = *(UINT32 *)(dwAddr + sizeof(uint32_t));
	
   if ( (dwStkPtr < SRAM_BASE) || ((dwStkPtr & 0xFF000000) != SRAM_BASE || (dwJumpAddr < FLASH_APP_START_ADDR) || ((dwJumpAddr & 0xFF000000) != FLASH_BASE)) )
       return;
   for ( i = 0; i < 1000000; i ++)
      __NOP();
    
	IAP_Clear();

   SET_MSP(dwStkPtr);
   pfTarget = (void (*)(void))dwJumpAddr;
   pfTarget();   
}

我在使用例程的跳转函数中出现过:打印显示已经跳转成功,但实际并没有成功的情况。这里加个判断,未成功会重复打印,当然在项目中可以用其他现象来判断。

IAP_Clear函数里写了外设的时钟关闭,中断关闭和标志清除等等,可以根据自己的情况写,不加清除会出现跳转后卡死的情况。

实际起到跳转作用的是SET_MSP

注意

我把IAP放在了前面(0x08000000-0x08008000),APP放在了后面(0x08008000~)。上电后先执行IAP,在IAP初始化加了一个判断,不需要升级直接跳转到APP(也可以APP在前)

	if(UPFlag == RESET)
  {
    IAP_Jump(FLASH_APP_START_ADDR);
  }
	

APP内主函数里需要先加

SCB->VTOR=FLASH_BASE|0x00008000UL;

更改中断向量表。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值