[STM32H7] STM32H7 SDMMC+FATFS+USBMSC+FREERTOS 虚拟U盘

[复制链接]
3258|18
 楼主| liuqiangdong 发表于 2023-6-29 16:24 | 显示全部楼层 |阅读模式
通过cubemx配置 实现STM32H7 SDMMC+FATFS+USBMSC+FREERTOS 虚拟U盘

1.实验目的
1.使用FAFTS文件操作系统,实现STM32虚拟U盘,读写外部SD卡,fatfs和usb mass storage class共存。
2.请先完成上一个帖子的步骤 --> 跳转https://blog.csdn.net/hjn0618/article/details/130383593

2.实验平台
硬件平台:正点原子阿波罗 STM32H734IIT6
开发工具:STM32CubeIDE 1.12.0
HAL库:STM32Cube FW_H7 V1.11.0

 楼主| liuqiangdong 发表于 2023-6-29 16:25 | 显示全部楼层
3.CubeMX配置
(1)增加栈空间

43677649d3ff238e9e.png

 楼主| liuqiangdong 发表于 2023-6-29 16:26 | 显示全部楼层
配置FATFS
设置USE_LFN到STACK,防止文件名称过长,使FREERTOS内存溢出

26579649d401baed0b.png
 楼主| liuqiangdong 发表于 2023-6-29 16:26 | 显示全部楼层
开启FREERTOS
开启FreeRTOS后,USB_Device初始化函数再默认任务中,所以要增加默认的堆栈,
另外需要注意的是,开始FreeRTOS后,fatfs操作函数也必须在任务中,如f_mount等。

56318649d403400510.png
 楼主| liuqiangdong 发表于 2023-6-29 16:31 | 显示全部楼层
代码部分
重写usbd_storage_if.c,因为加入了FreeRTOS,fatfs对sd卡读写用的是发送消息机制,所以usbd_storage_if.c里的读写不能再去调用bsp_driver_sd.c里的读写方法了,大家有兴趣的可以对比一下有无FreeRTOS,bsp_driver_sd.c源码的内容
 楼主| liuqiangdong 发表于 2023-6-29 16:31 | 显示全部楼层
  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * [url=home.php?mod=space&uid=288409]@file[/url]           : usbd_storage_if.c
  5. * [url=home.php?mod=space&uid=895143]@version[/url]        : v1.0_Cube
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]          : Memory management layer.
  7. ******************************************************************************
  8. * @attention
  9. *
  10. * Copyright (c) 2023 STMicroelectronics.
  11. * All rights reserved.
  12. *
  13. * This software is licensed under terms that can be found in the LICENSE file
  14. * in the root directory of this software component.
  15. * If no LICENSE file comes with this software, it is provided AS-IS.
  16. *
  17. ******************************************************************************
  18. */
  19. /* USER CODE END Header */

  20. /* Includes ------------------------------------------------------------------*/
  21. #include "usbd_storage_if.h"

  22. /* USER CODE BEGIN INCLUDE */
  23. #include "fatfs.h"
  24. #include "stdio.h"
  25. /* USER CODE END INCLUDE */

  26. /* Private typedef -----------------------------------------------------------*/
  27. /* Private define ------------------------------------------------------------*/
  28. /* Private macro -------------------------------------------------------------*/

  29. /* USER CODE BEGIN PV */
  30. /* Private variables ---------------------------------------------------------*/
  31. extern SD_HandleTypeDef hsd1;
  32. /* USER CODE END PV */

  33. /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
  34.   * @brief Usb device.
  35.   * @{
  36.   */

  37. /** @defgroup USBD_STORAGE
  38.   * @brief Usb mass storage device module
  39.   * @{
  40.   */

  41. /** @defgroup USBD_STORAGE_Private_TypesDefinitions
  42.   * @brief Private types.
  43.   * @{
  44.   */

  45. /* USER CODE BEGIN PRIVATE_TYPES */

  46. /* USER CODE END PRIVATE_TYPES */

  47. /**
  48.   * @}
  49.   */

  50. /** @defgroup USBD_STORAGE_Private_Defines
  51.   * @brief Private defines.
  52.   * @{
  53.   */

  54. #define STORAGE_LUN_NBR                  1
  55. #define STORAGE_BLK_NBR                  0x10000
  56. #define STORAGE_BLK_SIZ                  0x200

  57. /* USER CODE BEGIN PRIVATE_DEFINES */

  58. /* USER CODE END PRIVATE_DEFINES */

  59. /**
  60.   * @}
  61.   */

  62. /** @defgroup USBD_STORAGE_Private_Macros
  63.   * @brief Private macros.
  64.   * @{
  65.   */

  66. /* USER CODE BEGIN PRIVATE_MACRO */

  67. /* USER CODE END PRIVATE_MACRO */

  68. /**
  69.   * @}
  70.   */

  71. /** @defgroup USBD_STORAGE_Private_Variables
  72.   * @brief Private variables.
  73.   * @{
  74.   */

  75. /* USER CODE BEGIN INQUIRY_DATA_FS */
  76. /** USB Mass storage Standard Inquiry Data. */
  77. const int8_t STORAGE_Inquirydata_FS[] = {/* 36 */
  78. /* LUN 0 */

  79. 0x00, 0x80, 0x02, 0x02, (STANDARD_INQUIRY_DATA_LEN - 5), 0x00, 0x00, 0x00, 'S',
  80.                 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
  81.                 'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product      : 16 Bytes */
  82.                 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0', '.', '0', '1' /* Version      : 4 Bytes */
  83. };
  84. /* USER CODE END INQUIRY_DATA_FS */

  85. /* USER CODE BEGIN PRIVATE_VARIABLES */
  86. /* USER CODE END PRIVATE_VARIABLES */

  87. /**
  88.   * @}
  89.   */

  90. /** @defgroup USBD_STORAGE_Exported_Variables
  91.   * @brief Public variables.
  92.   * @{
  93.   */

  94. extern USBD_HandleTypeDef hUsbDeviceFS;

  95. /* USER CODE BEGIN EXPORTED_VARIABLES */

  96. /* USER CODE END EXPORTED_VARIABLES */

  97. /**
  98.   * @}
  99.   */

  100. /** @defgroup USBD_STORAGE_Private_FunctionPrototypes
  101.   * @brief Private functions declaration.
  102.   * @{
  103.   */

  104. static int8_t STORAGE_Init_FS(uint8_t lun);
  105. static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
  106. static int8_t STORAGE_IsReady_FS(uint8_t lun);
  107. static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
  108. static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
  109. static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
  110. static int8_t STORAGE_GetMaxLun_FS(void);

  111. /* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */

  112. /* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */

  113. /**
  114.   * @}
  115.   */

  116. USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
  117. {
  118.   STORAGE_Init_FS,
  119.   STORAGE_GetCapacity_FS,
  120.   STORAGE_IsReady_FS,
  121.   STORAGE_IsWriteProtected_FS,
  122.   STORAGE_Read_FS,
  123.   STORAGE_Write_FS,
  124.   STORAGE_GetMaxLun_FS,
  125.   (int8_t *)STORAGE_Inquirydata_FS
  126. };

  127. /* Private functions ---------------------------------------------------------*/
  128. /**
  129.   * @brief  Initializes the storage unit (medium) over USB FS IP
  130.   * @param  lun: Logical unit number.
  131.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  132.   */
  133. int8_t STORAGE_Init_FS(uint8_t lun)
  134. {
  135.   /* USER CODE BEGIN 2 */
  136.         UNUSED(lun);
  137.         return USBD_OK;
  138.   /* USER CODE END 2 */
  139. }

  140. /**
  141.   * @brief  Returns the medium capacity.
  142.   * @param  lun: Logical unit number.
  143.   * @param  block_num: Number of total block number.
  144.   * @param  block_size: Block size.
  145.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  146.   */
  147. int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
  148. {
  149.   /* USER CODE BEGIN 3 */
  150.         int8_t ret = -1;
  151.         HAL_SD_CardInfoTypeDef info;
  152.         ret = HAL_SD_GetCardInfo(&hsd1, &info);
  153.         *block_num = info.LogBlockNbr - 1;
  154.         *block_size = info.LogBlockSize;
  155.         return ret;
  156.   /* USER CODE END 3 */
  157. }

  158. /**
  159.   * @brief   Checks whether the medium is ready.
  160.   * @param  lun:  Logical unit number.
  161.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  162.   */
  163. int8_t STORAGE_IsReady_FS(uint8_t lun)
  164. {
  165.   /* USER CODE BEGIN 4 */
  166.         int8_t ret = -1;
  167.         UNUSED(lun);
  168.         if (HAL_SD_GetCardState(&hsd1) == HAL_SD_CARD_TRANSFER)
  169.                 ret = 0;
  170.         return ret;
  171.   /* USER CODE END 4 */
  172. }

  173. /**
  174.   * @brief  Checks whether the medium is write protected.
  175.   * @param  lun: Logical unit number.
  176.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  177.   */
  178. int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
  179. {
  180.   /* USER CODE BEGIN 5 */
  181.         UNUSED(lun);

  182.         return (USBD_OK);
  183.   /* USER CODE END 5 */
  184. }

  185. /**
  186.   * @brief  Reads data from the medium.
  187.   * @param  lun: Logical unit number.
  188.   * @param  buf: data buffer.
  189.   * @param  blk_addr: Logical block address.
  190.   * @param  blk_len: Blocks number.
  191.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  192.   */
  193. int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
  194. {
  195.   /* USER CODE BEGIN 6 */
  196.         int8_t ret = USBD_FAIL;
  197.         uint32_t timer;
  198.         if (HAL_SD_ReadBlocks_DMA(&hsd1, buf, blk_addr, blk_len) == HAL_OK) {
  199.                 ret = USBD_OK;
  200.         }

  201.         if (USBD_OK == ret) {
  202.                 timer = osKernelSysTick();
  203.                 while (HAL_SD_GetState(&hsd1) == HAL_SD_STATE_BUSY) {
  204.                         if (osKernelSysTick() - timer > 30 * 1000) {
  205.                                 return USBD_FAIL;
  206.                         }
  207.                 };
  208.                 timer = osKernelSysTick();
  209.                 while (HAL_SD_GetCardState(&hsd1) != HAL_SD_CARD_TRANSFER) {
  210.                         if (osKernelSysTick() - timer > 30 * 1000) {
  211.                                 return USBD_FAIL;
  212.                         }
  213.                 };
  214.         }
  215.         return USBD_OK;
  216.   /* USER CODE END 6 */
  217. }

  218. /**
  219.   * @brief  Writes data into the medium.
  220.   * @param  lun: Logical unit number.
  221.   * @param  buf: data buffer.
  222.   * @param  blk_addr: Logical block address.
  223.   * @param  blk_len: Blocks number.
  224.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  225.   */
  226. int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
  227. {
  228.   /* USER CODE BEGIN 7 */
  229.         int8_t ret = USBD_FAIL;
  230.         uint32_t timer;
  231.         if (HAL_SD_WriteBlocks_DMA(&hsd1, buf, blk_addr, blk_len) == HAL_OK) {
  232.                 ret = USBD_OK;
  233.         }
  234.         if (USBD_OK == ret) {
  235.                 timer = osKernelSysTick();
  236.                 while (HAL_SD_GetState(&hsd1) == HAL_SD_STATE_BUSY) {
  237.                         if (osKernelSysTick() - timer > 30 * 1000) {
  238.                                 return USBD_FAIL;
  239.                         }
  240.                 };
  241.                 timer = osKernelSysTick();
  242.                 while (HAL_SD_GetCardState(&hsd1) != HAL_SD_CARD_TRANSFER) {
  243.                         if (osKernelSysTick() - timer > 30 * 1000) {
  244.                                 return USBD_FAIL;
  245.                         }
  246.                 };
  247.         }

  248.         return USBD_OK;
  249.   /* USER CODE END 7 */
  250. }

  251. /**
  252.   * @brief  Returns the Max Supported LUNs.
  253.   * @param  None
  254.   * @retval Lun(s) number.
  255.   */
  256. int8_t STORAGE_GetMaxLun_FS(void)
  257. {
  258.   /* USER CODE BEGIN 8 */
  259.         HAL_SD_CardInfoTypeDef info;
  260.         HAL_SD_GetCardInfo(&hsd1, &info);

  261.         if (info.LogBlockNbr)
  262.                 return STORAGE_LUN_NBR - 1;
  263.         else
  264.                 return STORAGE_LUN_NBR - 2;

  265.   /* USER CODE END 8 */
  266. }

  267. /* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */

  268. /* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */

  269. /**
  270.   * @}
  271.   */

  272. /**
  273.   * @}
  274.   */

 楼主| liuqiangdong 发表于 2023-6-29 16:32 | 显示全部楼层
sd_diskio.c增加两个函数,用作usb msc时关闭消息,做文件管理接收消息
  1. /* USER CODE BEGIN ErrorAbortCallbacks */
  2. /*
  3. ==============================================================================================
  4. depending on the SD_HAL_Driver version, either the HAL_SD_ErrorCallback() or HAL_SD_AbortCallback()
  5. or both could be defined, activate the callbacks below when suitable and needed
  6. ==============================================================================================
  7. void BSP_SD_AbortCallback(void)
  8. {
  9. }

  10. void BSP_SD_ErrorCallback(void)
  11. {
  12. }
  13. */
  14. /* USER CODE END ErrorAbortCallbacks */

  15. /* USER CODE BEGIN lastSection */
  16. /* can be used to modify / undefine previous code or add new code */
  17. void SD_Delet_Queue(void) {
  18.         osMessageDelete(SDQueueID);
  19. }

  20. void SD_Create_Queue(void) {
  21.         osMessageQDef(SD_Queue, QUEUE_SIZE, uint16_t);
  22.         SDQueueID = osMessageCreate(osMessageQ(SD_Queue), NULL);
  23. }
  24. /* USER CODE END lastSection */
 楼主| liuqiangdong 发表于 2023-6-29 16:32 | 显示全部楼层
通过中断来判断usb连接状态
  1. /**
  2.   * @brief This function handles USB On The Go FS global interrupt.
  3.   */
  4. void OTG_FS_IRQHandler(void)
  5. {
  6.   /* USER CODE BEGIN OTG_FS_IRQn 0 */
  7.   /* USER CODE END OTG_FS_IRQn 0 */
  8.   HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
  9.   /* USER CODE BEGIN OTG_FS_IRQn 1 */
  10.   FILE_MGT_USB_CHECK(); // 自定义的函数
  11.   /* USER CODE END OTG_FS_IRQn 1 */
  12. }
 楼主| liuqiangdong 发表于 2023-6-29 16:33 | 显示全部楼层
USB连接状态检测任务
注意:该任务的优先级要高于默认任务的优先级,原因是先要执行HAL_SD_Init(&hsd1),才能开启USB_MSC,在STORAGE_Init_FS我没有调用HAL_SD_Init(&hsd1),HAL_SD_Init(&hsd1)已经在fatfs中调用了。
 楼主| liuqiangdong 发表于 2023-6-29 16:33 | 显示全部楼层
  1. static void FILE_MGT_USB_CHECK_TASK(const void *arg) {
  2.         uint8_t dev_state = 0;
  3.         osEvent event;
  4.         FatFs_Check();
  5.         for (;;) {

  6.                 event = osMessageGet(usbStateQueueHandle, osWaitForever);
  7.                 if (event.status == osEventMessage) {
  8.                         osMutexWait(sdFreeMutexHandle, osWaitForever);
  9.                         printf("hUsbDeviceFS:%d\n", (uint8_t) event.value.v);
  10.                         if ((uint8_t) event.value.v == USBD_STATE_ADDRESSED) {
  11.                                 dev_state = USBD_STATE_ADDRESSED;
  12.                         } else if ((dev_state == USBD_STATE_ADDRESSED)
  13.                                         && ((uint8_t) event.value.v == USBD_STATE_CONFIGURED)) {
  14.                                 Set_SD_WriteOrRead(0);
  15.                                 printf("usb connect\n");
  16.                         } else {
  17.                                 dev_state = 0;
  18.                                 Set_SD_WriteOrRead(1);
  19.                                 printf("usb disconnect\n");
  20.                         }
  21.                         osMutexRelease(sdFreeMutexHandle);
  22.                 }

  23.         }
  24. }
 楼主| liuqiangdong 发表于 2023-6-29 16:33 | 显示全部楼层
文件操作测试任务
  1. static void FILE_MGT_SD_TEST_TASK(const void *arg) {
  2.         osDelay(500);
  3.         for (;;) {
  4.                 osDelay(500);
  5.                 osMutexWait(sdFreeMutexHandle, osWaitForever);
  6.                 if (SDCard_EN) {
  7.                         FatFs_FileTest();
  8.                 } else {
  9.                         printf("禁止使用SD卡\n");
  10.                 }
  11.                 osMutexRelease(sdFreeMutexHandle);

  12.         }
  13. }
 楼主| liuqiangdong 发表于 2023-6-29 16:33 | 显示全部楼层
以上两个任务是互斥的,为了是检测USB连接状态时,等待fatfs文件操作完成后再禁用fatfs文件操作系统。
  1. // 使能/禁止SD卡读写 1允许 0禁止
  2. static void Set_SD_WriteOrRead(uint8_t en) {
  3.         if (en == 1) {
  4.                 SD_Create_Queue();
  5.                 SDCard_EN = 1;
  6.         } else {
  7.                 SD_Delet_Queue();
  8.                 SDCard_EN = 0;
  9.         }
  10. }
 楼主| liuqiangdong 发表于 2023-6-29 16:34 | 显示全部楼层
实验效果
插入USB后,禁用文件操作系统 24912649d41fa0539e.png
 楼主| liuqiangdong 发表于 2023-6-29 16:35 | 显示全部楼层
拔出USB后,使能文件操作系统 2838649d424b556d9.png
 楼主| liuqiangdong 发表于 2023-6-29 16:35 | 显示全部楼层
6.源码下载
https://download.csdn.net/download/hjn0618/87751815
周半梅 发表于 2023-12-1 08:10 | 显示全部楼层

引线长度就决定了其响应信号的波长
Pulitzer 发表于 2023-12-1 09:13 | 显示全部楼层

数字电压表(DVM)或仪器来测量效率
周半梅 发表于 2023-12-1 10:16 | 显示全部楼层

靠近功率开关管或整流器的电容分到的纹波电流远多于相距较远的电容分到的纹波电流
童雨竹 发表于 2023-12-1 11:09 | 显示全部楼层

任何一条PCB引线都可能成为天线
Wordsworth 发表于 2023-12-1 12:12 | 显示全部楼层

滤波电容、功率开关管或整流器、电感或变压器
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

97

帖子

0

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