将STM32 Flash的一部分虚拟为大容量存储设备 USB_Device

       【举报再看养成习惯,噢 不对,点赞再看 养成习惯。感谢支持】

        实验环境:STM32F103VET6         512KB Flash        64KB RAM

                        CubeMX生成代码+MDK编译

         

        简介:

        手中有给设备升级的工作,希望采用USB的方式。但是板卡没有外挂Flash,也不希望占用大量的RAM来接收数据,干脆直接使用Flash模拟成大容量存储设备。

        这样一来直接固件就直接写入Flash中了。然后找到固件的位置,就可以升级了。

        如下图所示:将APP2所用的区域作为 大容量存储设备使用的内存,其中就包括升级需要的bin文件。只需要找到bin文件的位置即可完成接下来的升级。

=============分割线=============

        CubeMX配置: 配置USB 为大容量存储设备

配置USB设备代码:usbd_storage_if.c文件

                                BLOCKNUM=400     STORAGE_BLK_SIZ=0x200    

                                即大容量存储设备容量=400*0x200=200KB

/* USER CODE BEGIN PRIVATE_TYPES */
#define BLOCKNUM  400
/* USER CODE END PRIVATE_TYPES */

#define STORAGE_LUN_NBR                  1
#define STORAGE_BLK_NBR                  BLOCKNUM
#define STORAGE_BLK_SIZ                  0x200

 STORAGE_BLK_SIZ=0x200 是指作为USB-Device时 一个扇区的大小。

其他函数配置: 

#define APP1_START_ADDR                     0x08019000

#define MASS_STORAGE_CLASS_START_ADDR       0x0804B000

/* Private functions ---------------------------------------------------------*/
/**
  * @brief  Initializes over USB FS IP
  * @param  lun:
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_Init_FS(uint8_t lun)
{
  /* USER CODE BEGIN 2 */
  return (USBD_OK);
  /* USER CODE END 2 */
}

/**
  * @brief  .
  * @param  lun: .
  * @param  block_num: .
  * @param  block_size: .
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
  /* USER CODE BEGIN 3 */
  *block_num  = STORAGE_BLK_NBR;
  *block_size = STORAGE_BLK_SIZ;
  return (USBD_OK);
  /* USER CODE END 3 */
}

/**
  * @brief  .
  * @param  lun: .
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
  /* USER CODE BEGIN 4 */

  // return (USBD_FAIL);
  return (USBD_OK);
  /* USER CODE END 4 */
}

/**
  * @brief  .
  * @param  lun: .
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
{
  /* USER CODE BEGIN 5 */
  return (USBD_OK);
  /* USER CODE END 5 */
}

/**
  * @brief  .
  * @param  lun: .
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 6 */
  uint32_t satrtAddr = MASS_STORAGE_CLASS_START_ADDR + blk_addr*STORAGE_BLK_SIZ;
  for(uint16_t i=0;i<blk_len*STORAGE_BLK_SIZ;i++){
    *(buf+i) = STMFLASH_ReadByte(satrtAddr+i);
  }
  return (USBD_OK);
  /* USER CODE END 6 */
}

/**
  * @brief  .
  * @param  lun: .
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */

unsigned char tempBuff[2048] = {0};

int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 7 */
  uint32_t * p = (uint32_t *)tempBuff;
	FLASH_EraseInitTypeDef FlashEraseInit;
	uint32_t PageError = 0;
  // 要写入的地址
  uint32_t falshAddr = MASS_STORAGE_CLASS_START_ADDR + blk_addr*STORAGE_BLK_SIZ;
  // 要写入的地址所在的扇区的起始地址
  uint32_t sectorStartAddr = Get103VET6SectorAddr(falshAddr);
  uint32_t tempSectorStartAddr = sectorStartAddr;
  // 判断要写的内容在Flash哪一个扇区  将其中的内容全部取出到Buff中
  memcpy(tempBuff, (uint32_t *)sectorStartAddr, 2048);

  // 将数据写入Buff
  memcpy(tempBuff+(blk_addr%4)*512, buf, blk_len*512);
  SEGGER_RTT_printf(0,"addr %x  start addr %x \r\n",falshAddr,sectorStartAddr);
	HAL_FLASH_Unlock();                         //解锁	
  // // 擦除当前Flash扇区内容
  FlashEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;    //擦除类型,页擦除 
  FlashEraseInit.Banks = FLASH_BANK_1;   	
  FlashEraseInit.PageAddress = falshAddr;
  FlashEraseInit.NbPages = 1;                          //一次只擦除一页
  if(HAL_FLASHEx_Erase(&FlashEraseInit, &PageError) != HAL_OK) 
  {
    SEGGER_RTT_printf(0,"Flash Erase err\r\n");
	  HAL_FLASH_Lock();      
    return (USBD_FAIL);
  }
  FLASH_WaitForLastOperation(FLASH_WAITETIME);            //等待上次操作完成
  SEGGER_RTT_printf(0,"Flash Erase OK\r\n");

  // 将整个Buff存入Flash
  while(sectorStartAddr < tempSectorStartAddr+2048)									//写数据
  {	  //  单次写入8字节 64位数据
    if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, sectorStartAddr, *(uint64_t*)p) != HAL_OK)//写入数据
    {
	    HAL_FLASH_Lock();      
      return (USBD_FAIL);
      break;												//写入异常
    }
    sectorStartAddr += 8;     //地址加8
    p += 2;       //buff是32位的,所以这里+2 便是8个字节
  }  

	FLASH_WaitForLastOperation(FLASH_WAITETIME);        //等待上次操作完成
	HAL_FLASH_Lock();      

  return (USBD_OK);
  /* USER CODE END 7 */
}

/**
  * @brief  .
  * @param  None
  * @retval .
  */
int8_t STORAGE_GetMaxLun_FS(void)
{
  /* USER CODE BEGIN 8 */
  // SEGGER_RTT_printf(0," STORAGE_GetMaxLun_FS  %d \r\n",STORAGE_LUN_NBR - 1);
  return (STORAGE_LUN_NBR - 1);
  /* USER CODE END 8 */
}

主要是写入和读取函数配置:

int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)

写入:buf为要写入数据的指针、blk_addr为要写入的块的index、blk_len为要写入几个块(一般为1)

        因为103VET6的flash块大小为2K,所以要判断blk_addr在那个Flash块中,然后将整个Flash块读出来重新写入。blk_len一般为1,所以如果不为1时,这段代码是有问题的。

int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)

读取:参数同写入,用到了读取单个字节的函数

/*************************************************************
** Function name:       STMFLASH_ReadByte
** Descriptions:        读uint8操作
** Input parameters:    None
** Output parameters:   None
** Returned value:      None
** Remarks:             None
*************************************************************/
uint8_t STMFLASH_ReadByte(uint32_t faddr)
{
	return *(uint8_t*)faddr; 
}

然后我们利用写入文件连续的特性,就可以在内存中得到bin文件了。

实验:

可以看出来,固件拷贝到优盘之后,在0x0805 0600的位置。和bin文件是一样的。

重新上电U盘中的内容也会存在,不会因为掉电丢失。 

#define APP1_START_ADDR                     0x08019000

#define MASS_STORAGE_CLASS_START_ADDR       0x0804B000

 大容量存储设备 起始地址为0x0804B000, 在固件之前的内容为FAT系统的其他数据。

【我们可以在Bin文件开头 做上Information(名字+版本号+StartAddr+CRC等等),结尾做上结束标记符号,这样就能判断是不是需要升级的固件】

 注意事项:升级的话U盘中只能放一个固件文件、放其他的可能会使文件内容不连续。具体可以搜一下FAT系统。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: STM32 USB Device Library 是专为 STM32 微控制器设计的 USB 设备库。它提供了一套 API 接口供开发者使用,以便在 STM32 上实现 USB 设备功能。 要下载 STM32 USB Device Library,首先我们需要访问 ST 微电子官方网站。在该网站上,我们可以找到 STM32Cube 软件开发套件的下载页面。在这个页面上,我们可以选择需要的 STM32 系列以及芯片型号,并下载相应的软件包。 在 STM32Cube 软件开发套件中,STM32 USB Device Library 是其中的一部分。下载和安装 STM32Cube 软件开发套件后,我们就可以获得 STM32 USB Device Library 的最新版本。 一旦获得了 STM32 USB Device Library,我们可以将其添加到我们的项目中。我们可以通过复制库文件或者链接库的方式将 STM32 USB Device Library 添加到我们的 IDE(集成开发环境)中。接下来,我们需要在我们的代码中包含 USB Device Library 的头文件,并使用提供的 API 接口来实现 USB 设备功能。 当我们完成编写代码和配置项目后,我们可以编译和下载我们的代码到 STM32 微控制器上。通过正确配置和使用 STM32 USB Device Library,我们的 STM32 设备可以通过 USB 接口与计算机或其他 USB 主机设备进行通信。 总之,STM32 USB Device Library 是用于实现 USB 设备功能的库,可以通过访问 ST 微电子官方网站并下载 STM32Cube 软件开发套件来获取最新版本。下载并添加库文件后,我们可以在代码中使用提供的 API 接口来实现我们的 USB 设备功能。 ### 回答2: STM32 USB device library是STMicroelectronics官方提供的用于STM32微控制器的USB设备库。该库包含了用于实现USB设备功能的各种驱动程序和例程。 要下载STM32 USB device library,您可以按照以下步骤进行操作: 1. 访问STMicroelectronics官方网站。您可以通过搜索引擎输入关键词"STMicroelectronics"来找到官方网站。 2. 在官方网站首页或导航栏中,找到"产品"或"开发工具"类别,并点击进入。 3. 在"产品"或"开发工具"类别中,选择"微控制器"或"STM32系列",会显示出支持的STM32微控制器的产品列表或开发工具。 4. 在产品列表中,找到您所使用的STM32微控制器型号,并点击进入相关页面。 5. 在该页面中,应该能找到相关的软件、固件和驱动程序。在其中寻找与USB设备库相关的下载链接。 6. 点击下载链接,选择适合您的操作系统的版本,并进行下载。 另外,您也可以通过在搜索引擎中输入"STM32 USB device library下载"等关键词来查找其他第三方网站或开发者社区,这些网站可能提供了更多的资源和下载选项。 一旦您下载了STM32 USB device library,您可以解压缩并将其添加到您的STM32项目中。然后,您可以按照官方提供的文档和示例代码来使用该库,实现您所需的USB设备功能。 请注意,为了使用STM32 USB device library,您需要具备一定的嵌入式系统和STM32微控制器的编程知识。建议您在使用该库之前仔细阅读相关的官方文档和示例代码,以确保正确地集成和使用该库。 ### 回答3: STM32 USB Device库是STMicroelectronics专为其STM32系列微控制器开发的一款USB设备协议库。对于需要在STM32微控制器上实现USB设备功能的开发者来说,这个库是非常有用的。 要下载STM32 USB Device库,可以按照以下步骤操作: 1. 首先,访问STMicroelectronics的官方网站。在搜索栏中输入“STM32 USB Device库”进行搜索。 2. 在搜索结果中找到STMicroelectronics官方网站上的下载页面或者产品页面。点击进入该页面。 3. 在该页面寻找能够下载STM32 USB Device库的链接或者按钮。通常,这些链接或按钮位于页面的底部或者页面上的特定区域。 4. 点击下载链接或按钮,开始下载STM32 USB Device库的压缩文件。这个文件包含了库的源代码和相应的文档。 5. 下载完成后,解压缩文件到一个你指定的文件夹中。 一旦STM32 USB Device库被下载和解压缩,你可以在你的STM32工程项目中使用该库。使用该库的具体步骤可能因为不同的开发环境或者IDE而有所不同。一般来说,在你的开发环境中,你需要将库的源代码加入到你的项目中,并且配置项目设置以允许使用该库。 使用STM32 USB Device库,你可以方便地在STM32微控制器上实现各种USB设备功能,比如USB存储设备虚拟串口设备等。这个库提供了丰富的API和示例代码,帮助你快速构建并调试你的USB设备应用程序。 总之,STM32 USB Device库是STMicroelectronics为STM32微控制器开发的一款USB设备协议库,可以通过STMicroelectronics的官方网站进行下载,并提供了丰富的API和示例代码帮助你在STM32微控制器上实现USB设备功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值