[STM32H7] 【STM32H745I-DISCO试用】5、eMMC+USB MSC=U盘

[复制链接]
 楼主| sujingliang 发表于 2025-1-23 18:55 | 显示全部楼层 |阅读模式
<
本帖最后由 sujingliang 于 2025-1-23 19:04 编辑

本文记录将STM32H745I-DISCO配置为USB DEVICE - MSC设备的过程,U盘存储设备为板载eMMC。


一、电路图
28.png

29.png
板载eMMC型号为MTFC4GACAJCN,4Gbytes eMMC设备。eMMC是一种将NAND闪存和一个控制器集成在一个单独的封装中的存储设备。

二、STM32CuteMX配置
1、SDMMC1
mode:MMC 8 bits Wide bus,
分频:2或者1
30.png

2、USB_OTG_FS
USB MODE:Device only
参数设置保持默认
31.png

3、USB_DEVICE_M7
CLASS:Mass Storage Class
参数设置保持默认,注意缓存为512bytes
32.png
4、时钟配置

SDMMC配置为50Mhz:
36.png

USB固定为48Mhz

37.png
生成代码

三、代码修改
为了将USB配置为MSC设备,需要是在usbd_storage_if.c实现以下几个函数,用来和EMMC设备通信:

USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
{
  STORAGE_Init_FS,
  STORAGE_GetCapacity_FS,//必须实现
  STORAGE_IsReady_FS,//必须实现
  STORAGE_IsWriteProtected_FS,
  STORAGE_Read_FS,//必须实现
  STORAGE_Write_FS,//必须实现
  STORAGE_GetMaxLun_FS,
  (int8_t *)STORAGE_Inquirydata_FS
};


1、STORAGE_Init_FS
SDMMC设备在main()中已经初始化,这里直接返回
  1. int8_t STORAGE_Init_FS(uint8_t lun)
  2. {
  3.   /* USER CODE BEGIN 2 */
  4.   return (USBD_OK);
  5.   /* USER CODE END 2 */
  6. }
2、STORAGE_GetCapacity_FS
这个函数用来获得存储单元block的大小和个数,对于eMMC,每个存储单元block为512bytes
  1. int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
  2. {
  3.   /* USER CODE BEGIN 3 */
  4.         
  5. HAL_MMC_CardInfoTypeDef info;
  6. HAL_MMC_CardStateTypeDef State;

  7.   State = HAL_MMC_GetCardState(&hmmc1);
  8.   if(State == HAL_MMC_CARD_TRANSFER)
  9.   {
  10.     HAL_MMC_GetCardInfo(&hmmc1, &info);
  11.    *block_num = info.LogBlockNbr - 1;
  12.    *block_size = info.LogBlockSize;
  13.     return (USBD_OK);
  14.   }
  15.   else
  16.         while(1);
  17.   /* USER CODE END 3 */
  18. }
3、STORAGE_IsReady_FS
检查存储是否可用
  1. int8_t STORAGE_IsReady_FS(uint8_t lun)
  2. {
  3.   /* USER CODE BEGIN 4 */
  4.   uint8_t state = 0;
  5.   state = HAL_MMC_GetState(&hmmc1) ;
  6.   if(HAL_MMC_STATE_READY != state)
  7.   {
  8.           return USBD_FAIL ;
  9.   }

  10.   return (USBD_OK);
  11.   /* USER CODE END 4 */
  12. }
4、读函数
  1. int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
  2. {
  3.   /* USER CODE BEGIN 6 */
  4.   int8_t ret = USBD_FAIL;
  5.   uint32_t timeout = 100000;
  6.         if( HAL_MMC_ReadBlocks(&hmmc1,(uint8_t *)buf, blk_addr , blk_len, timeout) == HAL_OK)
  7.         {
  8.                 while(((HAL_MMC_GetCardState(&hmmc1)== HAL_MMC_CARD_TRANSFER)?MMC_TRANSFER_OK:MMC_TRANSFER_BUSY)!=HAL_OK)
  9.                 {
  10.                         ret=USBD_OK;
  11.                 }
  12.         }
  13.         
  14.         return ret;
  15.   /* USER CODE END 6 */
  16. }
5、写函数
  1. int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
  2. {
  3.   /* USER CODE BEGIN 7 */
  4.         int8_t ret = USBD_FAIL;
  5.   uint32_t timeout = 100000;        
  6.         
  7.         
  8.         if( HAL_MMC_WriteBlocks(&hmmc1,(uint8_t *)buf, blk_addr , blk_len, timeout) == HAL_OK)
  9.         {
  10.                 while(((HAL_MMC_GetCardState(&hmmc1)== HAL_MMC_CARD_TRANSFER)?MMC_TRANSFER_OK:MMC_TRANSFER_BUSY)!=HAL_OK)
  11.                 {
  12.                         ret=USBD_OK;
  13.                 }
  14.         }
  15.                 return ret;
  16.         
  17.   /* USER CODE END 7 */
  18. }

三、运行效果

3.jpg
取电跳线改为USB FS,

连接USB FS和电脑:
33.png
设备管理器中,多出一个USB大容量存储设备。

第一次使用需要格式化,格式化参数选择如下:

35.png

完成后,就可以看到盘符和容量:

34.png


codingtuzi 发表于 2025-1-26 09:49 | 显示全部楼层
这个实验的技术含量好高啊
稳稳の幸福 发表于 2025-1-26 18:18 | 显示全部楼层
在里面放个PE系统,然后试试能否被电脑启动程序识别。
星辰大海不退缩 发表于 2025-1-30 14:06 | 显示全部楼层
eMMC+USB非常经典的控制方式
您需要登录后才可以回帖 登录 | 注册

本版积分规则

84

主题

146

帖子

3

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