[STM32L4] stm32L4xx 通过USB DFU功能升级固件

[复制链接]
2931|4
 楼主| dongnanxibei 发表于 2018-1-26 15:33 | 显示全部楼层 |阅读模式
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是否插入的状态读取。
  1. /**
  2.   * [url=home.php?mod=space&uid=247401]@brief[/url]  SetupStage callback.
  3.   * @param  hpcd: PCD handle
  4.   * @retval None
  5.   */
  6. void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
  7. {
  8.     /*监测到USB插入后,亮绿灯,并且把标志位置1*/
  9.     BSP_LED_On(LED_GREEN);
  10.     usb_dfu_is_activated = 1;
  11.     USBD_LL_SetupStage(hpcd->pData, (uint8_t *)hpcd->Setup);
  12. }

  13. /*main 函数*/
  14. int main(void)
  15. {


  16.   /* Initialize the HAL Library */
  17.   HAL_Init();

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

  20.   /* Enable Power Clock*/
  21.   __HAL_RCC_PWR_CLK_ENABLE();

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

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

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

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

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

  33.   /* Start Device Process */
  34.   USBD_Start(&USBD_Device);
  35.   //等待5s
  36.   HAL_Delay(5000);
  37.   if(usb_dfu_is_activated == 1){
  38.        /* Run Application (Interrupt mode) */
  39.       while(1){


  40.       }

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

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


  55.     }

  56.   }

  57.   while(1){

  58.   }      

  59. }



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


 楼主| dongnanxibei 发表于 2018-1-26 15:37 | 显示全部楼层
  • 升级固件
    使用官方提供的DfuSe_Demo_V3.0.5(stsw-stm32080.zip),成功安装后,使用DfuFileMgr.exe生成dfu文件。通过DfuSeDemo.exe下载固件
    1.png
    2.png
    3.png
  • 验证
    断电,拔掉USB,重启设备,检验是否运行正常。

mmuuss586 发表于 2018-1-26 17:17 | 显示全部楼层
感谢分享;
xinpian101 发表于 2018-1-28 11:24 | 显示全部楼层
USB的BootLoader吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

225

主题

3870

帖子

18

粉丝
快速回复 在线客服 返回列表 返回顶部