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

这篇具有很好参考价值的文章主要介绍了STM32H7 SDMMC+FATFS+USBMSC+FREERTOS 虚拟U盘。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

通过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

3.CubeMX配置

(1)增加栈空间
stm32模拟u盘,STM32,stm32,单片机,嵌入式硬件
(2)配置FATFS
设置USE_LFN到STACK,防止文件名称过长,使FREERTOS内存溢出
stm32模拟u盘,STM32,stm32,单片机,嵌入式硬件

(2)开启FREERTOS
开启FreeRTOS后,USB_Device初始化函数再默认任务中,所以要增加默认的堆栈,
另外需要注意的是,开始FreeRTOS后,fatfs操作函数也必须在任务中,如f_mount等。
stm32模拟u盘,STM32,stm32,单片机,嵌入式硬件

4.代码部分

重写usbd_storage_if.c,因为加入了FreeRTOS,fatfs对sd卡读写用的是发送消息机制,所以usbd_storage_if.c里的读写不能再去调用bsp_driver_sd.c里的读写方法了,大家有兴趣的可以对比一下有无FreeRTOS,bsp_driver_sd.c源码的内容

/* 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增加两个函数,用作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 */

通过中断来判断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 */
}

USB连接状态检测任务
注意:该任务的优先级要高于默认任务的优先级,原因是先要执行HAL_SD_Init(&hsd1),才能开启USB_MSC,在STORAGE_Init_FS我没有调用HAL_SD_Init(&hsd1),HAL_SD_Init(&hsd1)已经在fatfs中调用了。

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

	}
}

文件操作测试任务

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

	}
}

以上两个任务是互斥的,为了是检测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;
	}
}

5.实验效果

插入USB后,禁用文件操作系统
stm32模拟u盘,STM32,stm32,单片机,嵌入式硬件
拔出USB后,使能文件操作系统
stm32模拟u盘,STM32,stm32,单片机,嵌入式硬件

6.源码下载

https://download.csdn.net/download/hjn0618/87751815文章来源地址https://www.toymoban.com/news/detail-684629.html

到了这里,关于STM32H7 SDMMC+FATFS+USBMSC+FREERTOS 虚拟U盘的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32H7系列MCU的MPU和Cache功能介绍

    参考资料 :PM0253 STM32F7 Series and STM32H7 Series Cortex®-M7 processor programming manualV5.0 1.1 MPU 的作用 防止不受信任的应用程序访问受保护的内存区域; 防止用户应用程序破坏操作系统使用的数据;通过阻止任务访问其它任务的数据区;允许将内存区域定义为只读,以便保护重要数据;

    2024年02月01日
    浏览(31)
  • STM32H7使用QSPI外扩flash(linux下使用openocd操作)

    根据安福莱的STM32H7教程,H7单片机的QSPI外设是直接连到芯片内核上的,地址是0X90000000;那么就可以通过QSPI外设,将外置flash内存映射,并由此执行代码。 相关操作在keil5上比较简单,配置点东西就行;可以参考安福莱教程。 这里要介绍的是在linux环境下没有keil5 IDE的情况下

    2024年01月16日
    浏览(41)
  • STM32H7并行读取AD7606数据以及片内AD值不准解决办法

    先了解一下AD7606,16位,单电源,200k采样率,8路,除了贵没有其他缺点,数据相当的稳,一个5V供电,不用运放的情况下采集电压精度可以达到1mv,非常Nice 与单片机相连 单片机 调用代码 测试发现AD采集到的电压要远小于实际电压,H7的AD还是16位的,不能这么拉跨吧,在网上

    2024年02月11日
    浏览(31)
  • STM32CubeMX+FATFS+FREERTOS读写U盘

    软件:STM32CubeMX V6.6.1 、 KEIL5 V5.29 硬件:STM32F429ZET6 USB_OTG_FS:PA11/PA12引脚 USART1:PA9/PA10,方便输出调试信息 1)SYS下载方式选择SW方式,因为要使用FREERTOS,提前将时钟源修改为TIM7(其他定时器也可以) 2) RCC设置,选择高速外部晶振HSE(根据具体硬件选择) 3)USART1设置,方便输出调

    2024年01月18日
    浏览(34)
  • STM32H743使用CubeMX配置Lwip、Freertos

    硬件:野火挑战者开发板STM32H743IIT6 软件版本: CubeMX 6.7.0 STM32CubeH7 Firmware Package V1.11.0 / 04-Nov-2022 原理图: 时钟树参数仅供参考 MPU配置需要查相关资料,一知半解 修改GPIO与硬件原理图对应,串口参数默认 参数配置与硬件对应 此处网络收发地址非常重要!!! 使能中断 串口

    2024年02月07日
    浏览(39)
  • 【STM32H7 开发笔记】| 02 - 通过定时器级联方式同步启动多个定时器并输出 PWM 波形

    (STM32H723xE/G) 所有定时器包括 两个高级控制定时器、十二个通用定时器、两个基本定时器、五个低功耗定时器、两个看门狗定时器和一个SysTick定时器 。所有计时器计数器都可以在Debug模式下冻结。 本次实验主频配置的是500MHz 高级控制定时器(TIM1,TIM8)可以看作是在6通道

    2024年02月14日
    浏览(24)
  • STM32使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事项

    以STM32F429为例: 1、SDIO配置 配置为4bit模式,此配置不是最终配置,后面会在代码进行修改。 2、Fatfs配置 Set Defines 选项中的配置可以默认,最重要注意Advanced Setting 选择中的配置,如下 该界面配置默认Use dma template是默认使能的 ,并且不可以选择,只能选择使能,所以需要使

    2024年02月11日
    浏览(45)
  • STM32H723配置以太网+Freertos注意事项

    由于STM32H743涨价到300元以上,项目换用了Pin2Pin替换的STM32H723,看上去cpu运行速度快了20%达到550Mhz。 但是内存布局存在很大不一样,而且ST官方代码库升级迭代快,要手动修改地方每个版本不一样,在有H743的经验下,花了2天时间搞好了记录一下。很多信息来源于英文ST支持论

    2023年04月18日
    浏览(26)
  • cubmx基础操作,hal库基本配置流程之使用 stm32cubmx生成HAL库进行gpio点亮led(stm32h7xx)(超详细,小白教程)

    HAL库(硬件抽象层库)是一个提供对底层硬件操作的抽象的库,它使得开发者可以使用统一的接口进行硬件操作,而不必关心底层硬件的具体实现细节。HAL库通常由硬件厂商提供,用于支持其硬件设备,并为其提供标准化的接口。 HAL库的主要目的是简化底层硬件的操作,使得

    2024年02月20日
    浏览(42)
  • 【单片机学习笔记】Windows+Vscode+STM32F4+freeRTOS+FatFs gcc环境搭建

    为摒弃在接受keil邮件,研究了下gun编译,以STM32F407为例,简单记录 Git 选择对应版本直接安装即可https://git-scm.com/download/win make gcc ​ 1)将上述软件包放置于C盘根目录 2)添加环境变量 3)cmd命令行测试环境 分别输入 启动文件及LD文件 目录路径表示问题 字节对齐及指定位置存

    2024年02月07日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包