stm32L4xx 通过USB DFU功能升级固件

stm32L4xx 通过USB DFU功能升级固件

背景

因为项目需求,用户不方便用SWD模式下载程序,而且本设备也留有USB,因此考虑用USB DFU模式进行固件升级。
设备上使用的单片机是stm32l476,ST官方在单片机内部bootloader已经支持通过USB方式升级固件,但是需要通过修改MODE来切换是升级固件还是运行用户程序,设备本身也没有留修改mode的按键等,因此考虑修改使用USB DFU实现的IAP功能。

设计思路

设备上电后,5秒内没有检测到USB,那么进入用户程序区,如果检测到USB插入,进入Bootloader,等待下载固件。

实现步骤

  1. USB DFU Bootloader代码
    基本上完全使用了STM32Cube库中的例子,只是在它的基础上稍微做了修好,加入了usb是否插入的状态读取。
/**
  * @brief  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){

  }      

}
  1. 用户程序的编写
    • 用户程序主要是修改用户代码起始地址,需要注意的是这个地址要保持512字节的对齐,正常开发代码外,需要修改的地方有:
      我使用的是keil,在Option for Target里面配置IROM1,使其起始地址和Bootloader里面设置的一样(USBD_DFU_APP_DEFAULT_ADD),Size大小为总空间减去偏移的地址(本文中为0x100000 - 0x
      C000 = 0xF4000)
      stm32L4xx 通过USB DFU功能升级固件_第1张图片
    • 另一处是在system_stm32l4xx.c中, 定义VECT_TAB_OFFSET为0xC00,即偏移地址,默认是0x000。在默认情况下,芯片出厂内部的Bootloader会从0x8000000地址加载用户程序,修改后的地址偏移0xC00。
      stm32L4xx 通过USB DFU功能升级固件_第2张图片
    • 在Output配置生成hex文件
      stm32L4xx 通过USB DFU功能升级固件_第3张图片
  2. 升级固件
    使用官方提供的DfuSe_Demo_V3.0.5(stsw-stm32080.zip),成功安装后,使用DfuFileMgr.exe生成dfu文件。通过DfuSeDemo.exe下载固件
    stm32L4xx 通过USB DFU功能升级固件_第4张图片
    stm32L4xx 通过USB DFU功能升级固件_第5张图片
    stm32L4xx 通过USB DFU功能升级固件_第6张图片
  3. 验证
    断电,拔掉USB,重启设备,检验是否运行正常。

参考
[1]http://www.stmcu.org/module/forum/thread-606800-1-1.html
[2]http://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stsw-stm32080.html
[3]http://www.st.com/content/st_com/en/products/evaluation-tools/product-evaluation-tools/mcu-eval-tools/stm32-mcu-eval-tools/stm32-mcu-discovery-kits/32l476gdiscovery.html

你可能感兴趣的:(stm32,物联网)