打印
[STM32H7]

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

[复制链接]
1556|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
通过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)增加栈空间



使用特权

评论回复
板凳
liuqiangdong|  楼主 | 2023-6-29 16:26 | 只看该作者
配置FATFS
设置USE_LFN到STACK,防止文件名称过长,使FREERTOS内存溢出

使用特权

评论回复
地板
liuqiangdong|  楼主 | 2023-6-29 16:26 | 只看该作者
开启FREERTOS
开启FreeRTOS后,USB_Device初始化函数再默认任务中,所以要增加默认的堆栈,
另外需要注意的是,开始FreeRTOS后,fatfs操作函数也必须在任务中,如f_mount等。

使用特权

评论回复
5
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源码的内容

使用特权

评论回复
6
liuqiangdong|  楼主 | 2023-6-29 16:31 | 只看该作者
/* USER CODE BEGIN Header */
/**
******************************************************************************
* [url=home.php?mod=space&uid=288409]@file[/url]           : usbd_storage_if.c
* [url=home.php?mod=space&uid=895143]@version[/url]        : v1.0_Cube
* [url=home.php?mod=space&uid=247401]@brief[/url]          : Memory management layer.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */

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

/* USER CODE BEGIN INCLUDE */
#include "fatfs.h"
#include "stdio.h"
/* USER CODE END INCLUDE */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
extern SD_HandleTypeDef hsd1;
/* USER CODE END PV */

/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
  * @brief Usb device.
  * @{
  */

/** @defgroup USBD_STORAGE
  * @brief Usb mass storage device module
  * @{
  */

/** @defgroup USBD_STORAGE_Private_TypesDefinitions
  * @brief Private types.
  * @{
  */

/* USER CODE BEGIN PRIVATE_TYPES */

/* USER CODE END PRIVATE_TYPES */

/**
  * @}
  */

/** @defgroup USBD_STORAGE_Private_Defines
  * @brief Private defines.
  * @{
  */

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

/* USER CODE BEGIN PRIVATE_DEFINES */

/* USER CODE END PRIVATE_DEFINES */

/**
  * @}
  */

/** @defgroup USBD_STORAGE_Private_Macros
  * @brief Private macros.
  * @{
  */

/* USER CODE BEGIN PRIVATE_MACRO */

/* USER CODE END PRIVATE_MACRO */

/**
  * @}
  */

/** @defgroup USBD_STORAGE_Private_Variables
  * @brief Private variables.
  * @{
  */

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

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

/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */

/**
  * @}
  */

/** @defgroup USBD_STORAGE_Exported_Variables
  * @brief Public variables.
  * @{
  */

extern USBD_HandleTypeDef hUsbDeviceFS;

/* USER CODE BEGIN EXPORTED_VARIABLES */

/* USER CODE END EXPORTED_VARIABLES */

/**
  * @}
  */

/** @defgroup USBD_STORAGE_Private_FunctionPrototypes
  * @brief Private functions declaration.
  * @{
  */

static int8_t STORAGE_Init_FS(uint8_t lun);
static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
static int8_t STORAGE_IsReady_FS(uint8_t lun);
static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_GetMaxLun_FS(void);

/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */

/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */

/**
  * @}
  */

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
};

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

/**
  * @brief  Returns the medium capacity.
  * @param  lun: Logical unit number.
  * @param  block_num: Number of total block number.
  * @param  block_size: 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 */
        int8_t ret = -1;
        HAL_SD_CardInfoTypeDef info;
        ret = HAL_SD_GetCardInfo(&hsd1, &info);
        *block_num = info.LogBlockNbr - 1;
        *block_size = info.LogBlockSize;
        return ret;
  /* USER CODE END 3 */
}

/**
  * @brief   Checks whether the medium is ready.
  * @param  lun:  Logical unit number.
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
  /* USER CODE BEGIN 4 */
        int8_t ret = -1;
        UNUSED(lun);
        if (HAL_SD_GetCardState(&hsd1) == HAL_SD_CARD_TRANSFER)
                ret = 0;
        return ret;
  /* USER CODE END 4 */
}

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

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

/**
  * @brief  Reads data from the medium.
  * @param  lun: Logical unit number.
  * @param  buf: data buffer.
  * @param  blk_addr: Logical block address.
  * @param  blk_len: Blocks number.
  * @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 */
        int8_t ret = USBD_FAIL;
        uint32_t timer;
        if (HAL_SD_ReadBlocks_DMA(&hsd1, buf, blk_addr, blk_len) == HAL_OK) {
                ret = USBD_OK;
        }

        if (USBD_OK == ret) {
                timer = osKernelSysTick();
                while (HAL_SD_GetState(&hsd1) == HAL_SD_STATE_BUSY) {
                        if (osKernelSysTick() - timer > 30 * 1000) {
                                return USBD_FAIL;
                        }
                };
                timer = osKernelSysTick();
                while (HAL_SD_GetCardState(&hsd1) != HAL_SD_CARD_TRANSFER) {
                        if (osKernelSysTick() - timer > 30 * 1000) {
                                return USBD_FAIL;
                        }
                };
        }
        return USBD_OK;
  /* USER CODE END 6 */
}

/**
  * @brief  Writes data into the medium.
  * @param  lun: Logical unit number.
  * @param  buf: data buffer.
  * @param  blk_addr: Logical block address.
  * @param  blk_len: Blocks number.
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 7 */
        int8_t ret = USBD_FAIL;
        uint32_t timer;
        if (HAL_SD_WriteBlocks_DMA(&hsd1, buf, blk_addr, blk_len) == HAL_OK) {
                ret = USBD_OK;
        }
        if (USBD_OK == ret) {
                timer = osKernelSysTick();
                while (HAL_SD_GetState(&hsd1) == HAL_SD_STATE_BUSY) {
                        if (osKernelSysTick() - timer > 30 * 1000) {
                                return USBD_FAIL;
                        }
                };
                timer = osKernelSysTick();
                while (HAL_SD_GetCardState(&hsd1) != HAL_SD_CARD_TRANSFER) {
                        if (osKernelSysTick() - timer > 30 * 1000) {
                                return USBD_FAIL;
                        }
                };
        }

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

/**
  * @brief  Returns the Max Supported LUNs.
  * @param  None
  * @retval Lun(s) number.
  */
int8_t STORAGE_GetMaxLun_FS(void)
{
  /* USER CODE BEGIN 8 */
        HAL_SD_CardInfoTypeDef info;
        HAL_SD_GetCardInfo(&hsd1, &info);

        if (info.LogBlockNbr)
                return STORAGE_LUN_NBR - 1;
        else
                return STORAGE_LUN_NBR - 2;

  /* USER CODE END 8 */
}

/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */

/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */

/**
  * @}
  */

/**
  * @}
  */

使用特权

评论回复
7
liuqiangdong|  楼主 | 2023-6-29 16:32 | 只看该作者
sd_diskio.c增加两个函数,用作usb msc时关闭消息,做文件管理接收消息
/* USER CODE BEGIN ErrorAbortCallbacks */
/*
==============================================================================================
depending on the SD_HAL_Driver version, either the HAL_SD_ErrorCallback() or HAL_SD_AbortCallback()
or both could be defined, activate the callbacks below when suitable and needed
==============================================================================================
void BSP_SD_AbortCallback(void)
{
}

void BSP_SD_ErrorCallback(void)
{
}
*/
/* USER CODE END ErrorAbortCallbacks */

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

void SD_Create_Queue(void) {
        osMessageQDef(SD_Queue, QUEUE_SIZE, uint16_t);
        SDQueueID = osMessageCreate(osMessageQ(SD_Queue), NULL);
}
/* USER CODE END lastSection */

使用特权

评论回复
8
liuqiangdong|  楼主 | 2023-6-29 16:32 | 只看该作者
通过中断来判断usb连接状态
/**
  * @brief This function handles USB On The Go FS global interrupt.
  */
void OTG_FS_IRQHandler(void)
{
  /* USER CODE BEGIN OTG_FS_IRQn 0 */
  /* USER CODE END OTG_FS_IRQn 0 */
  HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
  /* USER CODE BEGIN OTG_FS_IRQn 1 */
  FILE_MGT_USB_CHECK(); // 自定义的函数
  /* USER CODE END OTG_FS_IRQn 1 */
}

使用特权

评论回复
9
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中调用了。

使用特权

评论回复
10
liuqiangdong|  楼主 | 2023-6-29 16:33 | 只看该作者
static void FILE_MGT_USB_CHECK_TASK(const void *arg) {
        uint8_t dev_state = 0;
        osEvent event;
        FatFs_Check();
        for (;;) {

                event = osMessageGet(usbStateQueueHandle, osWaitForever);
                if (event.status == osEventMessage) {
                        osMutexWait(sdFreeMutexHandle, osWaitForever);
                        printf("hUsbDeviceFS:%d\n", (uint8_t) event.value.v);
                        if ((uint8_t) event.value.v == USBD_STATE_ADDRESSED) {
                                dev_state = USBD_STATE_ADDRESSED;
                        } else if ((dev_state == USBD_STATE_ADDRESSED)
                                        && ((uint8_t) event.value.v == USBD_STATE_CONFIGURED)) {
                                Set_SD_WriteOrRead(0);
                                printf("usb connect\n");
                        } else {
                                dev_state = 0;
                                Set_SD_WriteOrRead(1);
                                printf("usb disconnect\n");
                        }
                        osMutexRelease(sdFreeMutexHandle);
                }

        }
}

使用特权

评论回复
11
liuqiangdong|  楼主 | 2023-6-29 16:33 | 只看该作者
文件操作测试任务
static void FILE_MGT_SD_TEST_TASK(const void *arg) {
        osDelay(500);
        for (;;) {
                osDelay(500);
                osMutexWait(sdFreeMutexHandle, osWaitForever);
                if (SDCard_EN) {
                        FatFs_FileTest();
                } else {
                        printf("禁止使用SD卡\n");
                }
                osMutexRelease(sdFreeMutexHandle);

        }
}

使用特权

评论回复
12
liuqiangdong|  楼主 | 2023-6-29 16:33 | 只看该作者
以上两个任务是互斥的,为了是检测USB连接状态时,等待fatfs文件操作完成后再禁用fatfs文件操作系统。
// 使能/禁止SD卡读写 1允许 0禁止
static void Set_SD_WriteOrRead(uint8_t en) {
        if (en == 1) {
                SD_Create_Queue();
                SDCard_EN = 1;
        } else {
                SD_Delet_Queue();
                SDCard_EN = 0;
        }
}

使用特权

评论回复
13
liuqiangdong|  楼主 | 2023-6-29 16:34 | 只看该作者
实验效果
插入USB后,禁用文件操作系统

使用特权

评论回复
14
liuqiangdong|  楼主 | 2023-6-29 16:35 | 只看该作者
拔出USB后,使能文件操作系统

使用特权

评论回复
15
liuqiangdong|  楼主 | 2023-6-29 16:35 | 只看该作者
6.源码下载
https://download.csdn.net/download/hjn0618/87751815

使用特权

评论回复
16
周半梅| | 2023-12-1 08:10 | 只看该作者

引线长度就决定了其响应信号的波长

使用特权

评论回复
17
Pulitzer| | 2023-12-1 09:13 | 只看该作者

数字电压表(DVM)或仪器来测量效率

使用特权

评论回复
18
周半梅| | 2023-12-1 10:16 | 只看该作者

靠近功率开关管或整流器的电容分到的纹波电流远多于相距较远的电容分到的纹波电流

使用特权

评论回复
19
童雨竹| | 2023-12-1 11:09 | 只看该作者

任何一条PCB引线都可能成为天线

使用特权

评论回复
20
Wordsworth| | 2023-12-1 12:12 | 只看该作者

滤波电容、功率开关管或整流器、电感或变压器

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

97

帖子

0

粉丝