通過cubemx配置 實(shí)現(xiàn)STM32H7 SDMMC+FATFS+USBMSC+FREERTOS 虛擬U盤
1.實(shí)驗(yàn)?zāi)康?/h2>
1.使用FAFTS文件操作系統(tǒng),實(shí)現(xiàn)STM32虛擬U盤,讀寫外部SD卡,fatfs和usb mass storage class共存。
2.請先完成上一個(gè)帖子的步驟 --> 跳轉(zhuǎn)https://blog.csdn.net/hjn0618/article/details/130383593
2.實(shí)驗(yàn)平臺
硬件平臺:正點(diǎn)原子阿波羅 STM32H734IIT6
開發(fā)工具:STM32CubeIDE 1.12.0
HAL庫:STM32Cube FW_H7 V1.11.0
3.CubeMX配置
(1)增加??臻g
(2)配置FATFS
設(shè)置USE_LFN到STACK,防止文件名稱過長,使FREERTOS內(nèi)存溢出
(2)開啟FREERTOS
開啟FreeRTOS后,USB_Device初始化函數(shù)再默認(rèn)任務(wù)中,所以要增加默認(rèn)的堆棧,
另外需要注意的是,開始FreeRTOS后,fatfs操作函數(shù)也必須在任務(wù)中,如f_mount等。
4.代碼部分
重寫usbd_storage_if.c,因?yàn)榧尤肓薋reeRTOS,fatfs對sd卡讀寫用的是發(fā)送消息機(jī)制,所以usbd_storage_if.c里的讀寫不能再去調(diào)用bsp_driver_sd.c里的讀寫方法了,大家有興趣的可以對比一下有無FreeRTOS,bsp_driver_sd.c源碼的內(nèi)容
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : usbd_storage_if.c
* @version : v1.0_Cube
* @brief : 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 */
/**
* @}
*/
/**
* @}
*/
sd_diskio.c增加兩個(gè)函數(shù),用作usb msc時(shí)關(guān)閉消息,做文件管理接收消息
/* 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 */
通過中斷來判斷usb連接狀態(tài)
/**
* @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(); // 自定義的函數(shù)
/* USER CODE END OTG_FS_IRQn 1 */
}
USB連接狀態(tài)檢測任務(wù)
注意:該任務(wù)的優(yōu)先級要高于默認(rèn)任務(wù)的優(yōu)先級,原因是先要執(zhí)行HAL_SD_Init(&hsd1),才能開啟USB_MSC,在STORAGE_Init_FS我沒有調(diào)用HAL_SD_Init(&hsd1),HAL_SD_Init(&hsd1)已經(jīng)在fatfs中調(diào)用了。
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);
}
}
}
文件操作測試任務(wù)
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);
}
}
以上兩個(gè)任務(wù)是互斥的,為了是檢測USB連接狀態(tài)時(shí),等待fatfs文件操作完成后再禁用fatfs文件操作系統(tǒng)。
// 使能/禁止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;
}
}
5.實(shí)驗(yàn)效果
插入U(xiǎn)SB后,禁用文件操作系統(tǒng)
拔出USB后,使能文件操作系統(tǒng)文章來源:http://www.zghlxwxcb.cn/news/detail-684629.html
6.源碼下載
https://download.csdn.net/download/hjn0618/87751815文章來源地址http://www.zghlxwxcb.cn/news/detail-684629.html
到了這里,關(guān)于STM32H7 SDMMC+FATFS+USBMSC+FREERTOS 虛擬U盤的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!