打印
[STM32L4]

stm32L4xx 通过USB DFU功能升级固件

[复制链接]
2413|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
stm32L4xx 通过USB DFU功能升级固件背景
因为项目需求,用户不方便用SWD模式下载程序,而且本设备也留有USB,因此考虑用USB DFU模式进行固件升级。
设备上使用的单片机是stm32l476,ST官方在单片机内部bootloader已经支持通过USB方式升级固件,但是需要通过修改MODE来切换是升级固件还是运行用户程序,设备本身也没有留修改mode的按键等,因此考虑修改使用USB DFU实现的IAP功能。
设计思路
设备上电后,5秒内没有检测到USB,那么进入用户程序区,如果检测到USB插入,进入Bootloader,等待下载固件。
实现步骤
  • USB DFU Bootloader代码
    基本上完全使用了STM32Cube库中的例子,只是在它的基础上稍微做了修好,加入了usb是否插入的状态读取。
/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  SetupStage callback.
  * @param  hpcd: PCD handle
  * @retval None
  */
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
{
    /*监测到USB插入后,亮绿灯,并且把标志位置1*/
    BSP_LED_On(LED_GREEN);
    usb_dfu_is_activated = 1;
    USBD_LL_SetupStage(hpcd->pData, (uint8_t *)hpcd->Setup);
}

/*main 函数*/
int main(void)
{


  /* Initialize the HAL Library */
  HAL_Init();

  /* Configure the system clock to 80 MHz */
  SystemClock_Config();

  /* Enable Power Clock*/
  __HAL_RCC_PWR_CLK_ENABLE();

  /* enable USB power on Pwrctrl CR2 register */
  HAL_PWREx_EnableVddUSB();

  /* Configure LED1, LED2, LED3 and LED4 */
  BSP_LED_Init(LED_GREEN);

  /* Otherwise enters DFU mode to allow user programing his application */
  /* Init Device Library */
  USBD_Init(&USBD_Device, &DFU_Desc, 0);

  /* Add Supported Class */
  USBD_RegisterClass(&USBD_Device, USBD_DFU_CLASS);

  /* Add DFU Media interface */
  USBD_DFU_RegisterMedia(&USBD_Device, &USBD_DFU_Flash_fops);

  /* Start Device Process */
  USBD_Start(&USBD_Device);
  //等待5s
  HAL_Delay(5000);
  if(usb_dfu_is_activated == 1){
       /* Run Application (Interrupt mode) */
      while(1){


      }

  }
  else{
      //    /* Test if user code is programmed starting from address 0x0800C000 */
    if(((*(__IO uint32_t*)USBD_DFU_APP_DEFAULT_ADD) & 0x2FFE0000 ) == 0x20000000)
    {
      //把USB停止掉,否则当用户程序运行后,插上USB也会检测到,但是是没有识别的USB设备
      USBD_Stop(&USBD_Device);
      USBD_DeInit(&USBD_Device);
      /* Jump to user application */
      JumpAddress = *(__IO uint32_t*) (USBD_DFU_APP_DEFAULT_ADD + 4);
      JumpToApplication = (pFunction) JumpAddress;

      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t*) USBD_DFU_APP_DEFAULT_ADD);
      JumpToApplication();


    }

  }

  while(1){

  }      

}



沙发
dongnanxibei|  楼主 | 2018-1-26 15:36 | 只看该作者
  • 用户程序的编写
    • 用户程序主要是修改用户代码起始地址,需要注意的是这个地址要保持512字节的对齐,正常开发代码外,需要修改的地方有:
      我使用的是keil,在Option for Target里面配置IROM1,使其起始地址和Bootloader里面设置的一样(USBD_DFU_APP_DEFAULT_ADD),Size大小为总空间减去偏移的地址(本文中为0x100000 - 0x
      C000 = 0xF4000)
    • 另一处是在system_stm32l4xx.c中, 定义VECT_TAB_OFFSET为0xC00,即偏移地址,默认是0x000。在默认情况下,芯片出厂内部的Bootloader会从0x8000000地址加载用户程序,修改后的地址偏移0xC00。
    • 在Output配置生成hex文件



使用特权

评论回复
板凳
dongnanxibei|  楼主 | 2018-1-26 15:37 | 只看该作者
  • 升级固件
    使用官方提供的DfuSe_Demo_V3.0.5(stsw-stm32080.zip),成功安装后,使用DfuFileMgr.exe生成dfu文件。通过DfuSeDemo.exe下载固件


  • 验证
    断电,拔掉USB,重启设备,检验是否运行正常。

使用特权

评论回复
地板
mmuuss586| | 2018-1-26 17:17 | 只看该作者
感谢分享;

使用特权

评论回复
5
xinpian101| | 2018-1-28 11:24 | 只看该作者
USB的BootLoader吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

201

主题

3587

帖子

16

粉丝