微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 之优盘自动升级固件(结项)

之优盘自动升级固件(结项)

时间:10-02 整理:3721RD 点击:
项目概述:
    结项弄的有点不完美希望小编,和各位同行见谅。
    自己做项目有用到了自动更新固件,所以想弄个更新程序。最近学习了心得固件库HAL 和stm32cubemx软件发现,节省了很多不必要的工作。所以准备以后的开发项目采用HAL库和stm32cubemx软件配合上来。

项目需求:

    开发板NUCLEO-F412ZG, miniusb的优盘,STM32cubeMx软件加java环境, STM32Cube_FW_F4_V1.14.0固件,keil5.

项目步骤:

    第一步.STM32cubeMx配置支持RCC高速外部时钟系统时钟100MHz.通过串口usart3收发数据作为调试信息。
   



    第二步.usb配置USB-host 采用mass storage host协议。 使用第三方库FATFS文件系统.
    有了这个系统我们的程序就能识别到优盘里的内容了。因为优盘大多都是FAT32格式的,为了方便识别升级固件文件。STM32cubeMx软件配置如下



第三部,配置系统时钟和USB时钟。
如图:


接下来就可以点击向齿轮一样的按钮生成源码工程了。不过在这之前要把工程配置设置好如图是本工程个人的设置。


编译IDE根据个人平台工具可选。
第四步.在keil5平台编辑,估计是STM32cubeMx的bug,每次自动生成工程代码都会把系统时钟的内部高速系统时钟配置上,有可能导致系统跑到这里就进error中断了。开始找了好一会才发现是它的问题。现在我经常会自动生成代码后把时钟改为外部晶振(RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;),编译调式运行下看看能不能成功的运行到结尾。
下面进入加入具体功能:
int main(void)
{
  /* USER CODE BEGIN 1 */
  uint8_t bootflag =  *(__IO uint8_t *) (UPDATA_FLAG);
  uint8_t i;
  uint32_t file_byte,file_byte_Index;
      /* USER CODE END 1 */
      /* MCU Configuration----------------------------------------------------------*/
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
      /* Configure the system clock */
      SystemClock_Config();
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      FLASH_If_Init();
      /* USER CODE BEGIN 2 */
      switch (bootflag)
      {
      case BOOT_FLAG_2NDBOOT_USB:
        MX_USART3_UART_Init();
        MX_USB_HOST_Init();
        MX_FATFS_Init();
        
        HAL_GPIO_WritePin(GPIOB, LD2_Pin, GPIO_PIN_SET);  
        printf("hello word\r\n");
        /* Register the file system object to the FatFs module */
        if(f_mount(&USBH_fatfs, "", 0) != FR_OK)
        {  
          USBH_ErrLog("ERROR : Cannot Initialize FatFs! \n");
        }
        HAL_GPIO_WritePin(USB_PowerSwitchOn_GPIO_Port, USB_PowerSwitchOn_Pin, GPIO_PIN_SET);
        /* USER CODE END 2 */
        /* Infinite loop */
        /* USER CODE BEGIN WHILE */
        while (1)
        {
        /* USER CODE END WHILE */
          MX_USB_HOST_Process();
          /* USER CODE BEGIN 3 */
          if(Appli_state == APPLICATION_READY)
          {
              if(f_open(&MyFile, "0:USBHost.bin", FA_READ) != FR_OK)
              {
                USBH_ErrLog("Cannot Open 'USBHost.bin' file for read.\n");
              }
              else
              {
                USBH_UsrLog("INFO : Text written on the 'USBHost.bin' file \n");
                FLASH_If_EraseApp();
                file_byte=f_size(&MyFile);
                for(file_byte_Index = 0; file_byte_Index < file_byte;)
                {
                  res = f_read(&MyFile, rtext, sizeof(rtext), (void *)&bytesread);
                  
                  if((bytesread == 0) || (res != FR_OK)) /*EOF or Error*/
                  {
                    USBH_ErrLog("Cannot Read from the  'USBHost.bin' file \n");
                    break;
                  }
                  else
                  {
                    USBH_UsrLog("Read bin : %d\n", bytesread);
                    FLASH_If_Write((APPLICATION_ADDRESS + file_byte_Index), (uint32_t *)rtext, (uint32_t)bytesread/4);
                    file_byte_Index += bytesread;
                  }
                }
                f_close(&MyFile);
                ///////////////////////////////////////////
                //ìáê??μí3ò??-?üD?íê3é
                //////////////////////////////////////
                IAP_Jump_App();
              }
          }
      
        }
        /* USER CODE END 3 */
        break;
    case BOOT_FLAG_2NDBOOT_UPDATE:
        
        break;
    case BOOT_FLAG_APP_NORMAL:
           //?′DD3ìDò
        IAP_Jump_App();
        break;
    default:
        i = GetSector(UPDATA_FLAG);
        EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
        EraseInitStruct .VoltageRange =VOLTAGE_RANGE_3 ;
        EraseInitStruct.Sector = i ;
        EraseInitStruct.NbSectors = 1;
        while(HAL_FLASHEx_Erase(&EraseInitStruct, (uint32_t *)&i) != HAL_OK);
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, UPDATA_FLAG, BOOT_FLAG_2NDBOOT_USB);
        //reset
        HAL_NVIC_SystemReset();
   }
   while (1)
   {;}
}
main实现了整个流程原来的代码是可以实现上电按按键进入二级boot模式但是由于自己的失误还原回去了。我使用的是64K作为二级boot.此处可以根据项目需求更改。


用到更改的文件都在application中。
串口打印的日志如图


实物图如下,这可多亏老婆的优盘要不还得用个OTG。


不知道描述的够详细不,如果有问题可以随时沟通,希望大家共同学习进步。
第五步.应用固件的开发
首先应用固件的起始地址编程0x8010000如图


这个需要生成.bin文件配置如图。


F:\Program Files\Keil5\ARM\ARMCC\bin\fromelf.exe --bin --output ./RTC/RTC.bin ./RTC/RTC.axf,根据自己的工程名,文件路径进行相应修改。
应用的功能就要看自己的实际需求了。我只是简单的实现相应RTC功能如上篇主题。
   
希望看到此文的童鞋,如果有什么想法提出来,帮忙指正自动升级这块应该怎么做比较好。大家一起学习。

IAP部分需要的可以参考我的串口IAP

学习了,谢谢!

学习了,谢谢!

谢谢小编的分享,学习了

谢谢分享,值得学习。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top