STM32 通过USB的Mass Storage Class读写挂载的SD卡出现卡死问题

问题描述:
使用stm32cubemx生成的sdio和usb Mass Storage Class的代码后,在USB_DEVICE\App\usbd_storage_if.c文件里面的接口调用以下函数出现卡死问题:
SD_Driver.disk_initialize(0);
SD_Driver.disk_read(lun, buf, blk_addr, blk_len)
SD_Driver.disk_write(lun, buf, blk_addr, blk_len);

解决办法:
1、STORAGE_Init_FS里面不直接调用disk_initialize,在MX_SDIO_SD_Init里面直接初始化sd卡,

2、读写sd卡的函数改为dma的读写接口:
HAL_SD_ReadBlocks_DMA(&hsd, buf, blk_addr, blk_len)
HAL_SD_WriteBlocks_DMA(&hsd, buf, blk_addr, blk_len)


USB_DEVICE\App\usbd_storage_if.c文件的具体代码如下:

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : usbd_storage_if.c* @version        : v1.0_Cube* @brief          : Memory management layer.******************************************************************************* @attention** Copyright (c) 2025 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 "sdio.h"
#include "sd_diskio.h"
#include "log_debug.h"
/* USER CODE END INCLUDE *//* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*//* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*//* 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/* 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 *///需要提取初始化sd卡,这里初始化sd卡会卡死if(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER){log_debug("STORAGE_Init_FS\n");return USBD_OK;}log_debug("STORAGE_Init_FS fail\n");return USBD_FAIL;/* 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 */HAL_SD_CardInfoTypeDef info;if(HAL_SD_GetCardState(&hsd) ==  HAL_SD_CARD_TRANSFER){HAL_SD_GetCardInfo(&hsd, &info);*block_num = info.LogBlockNbr;*block_size = info.LogBlockSize;//log_debug("SD_GetCardInfo: %d, %d\r\n", *block_num, *block_size);return  USBD_OK;}log_debug("STORAGE_GetCapacity_FS Fail !!!\n");return  USBD_FAIL;/* 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 */if(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER){return USBD_OK;}log_debug("STORAGE_IsReady_FS Fail !!!\n");return USBD_FAIL;/* 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 *///log_debug("STORAGE_IsWriteProtected_FS: %d\r\n", 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;  if( HAL_SD_ReadBlocks_DMA(&hsd, buf, blk_addr, blk_len) == HAL_OK )// if( HAL_SD_ReadBlocks(&hsd, buf, blk_addr,  blk_len, HAL_MAX_DELAY) == HAL_OK ){ret = USBD_OK;//while(HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY){};while( HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER ){};} else {ret = USBD_FAIL;log_debug("STORAGE_Read_FS Fail !!!\n");} return ret;/* 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; if( HAL_SD_WriteBlocks_DMA(&hsd, buf, blk_addr, blk_len) == HAL_OK )// if( HAL_SD_WriteBlocks(&hsd, buf, blk_addr, blk_len, HAL_MAX_DELAY) == HAL_OK ){ret = USBD_OK;//while(HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY){};while( HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER ){};}  else {ret = USBD_FAIL;log_debug("STORAGE_Write_FS Fail !!!\n");}return ret;/* 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 */
//   log_debug("STORAGE_GetMaxLun_FS: %d\r\n", STORAGE_LUN_NBR);return (STORAGE_LUN_NBR - 1);/* USER CODE END 8 */
}/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION *//* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION *//*** @}*//*** @}*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/98200.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/98200.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go语言中 error 接口与自定义错误类型的深入解析

在 Go 语言开发中,我们经常需要处理各种错误情况。Go 语言通过 error 接口提供了一套简洁而强大的错误处理机制。然而,当涉及到自定义错误类型时,许多开发者会遇到一些令人困惑的问题。本文将通过一个实际案例来深入探讨这个问题。 问题背景 …

字幕编辑工具推荐,Subtitle Edit v4.0.13发布:增强语音识别+优化翻译功能

大家好呀,不知道大家有没有做自媒体相关工作的呢,你们是不是也觉得剪辑视频时最头疼的往往不是画面而是字幕,时间轴对不上、格式不兼容、需要手动翻译,这些琐碎工作消耗的精力甚至超过剪辑本身。 当你试遍各种在线工具却发现要么…

【Java后端】Spring Boot 集成雪花算法唯一 ID

Spring Boot 实现基于雪花算法的分布式唯一 ID 生成器在分布式系统中,我们经常需要生成 全局唯一 ID,比如用户 ID、订单号、消息 ID 等。常见的方式有:数据库自增主键、UUID、Redis/Zookeeper 分布式 ID 服务、百度 UidGenerator、美团 Leaf …

C语言初尝试——洛谷

一、C数组:C 语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。声明数组在 C 中要声明一个数组,需要指定元素的类型和元素的数量&#xf…

C++八大排序

C排序算法一、概览二、代码实现1.冒泡排序2.插入排序3.希尔排序4.堆排序5.选择排序6.快速排序7.归并排序三、排序时间、空间复杂度总结排序,是C各大算法当中非常常见的一个步骤(过程),通常我们使用便捷的algorithmalgorithmalgori…

每天五分钟深度学习:深层神经网络的优势

本文重点 在人工智能领域,深层神经网络(DNN)的崛起标志着技术范式的根本性转变。相较于传统浅层神经网络(如单层感知机、线性回归模型),深层网络通过引入多层隐藏层,实现了对复杂数据模式的深度解析与高效建模。 深层神经网络 神经网络中输入层表示神经网络的第0层,…

相机几何 空间点到像素平面转换

一个空间中点到像素平面转换,需要经过1. 空间坐标系转换到相机坐标系2. 相机坐标系下3D点到相机平面转换3. 相机平面到像素平面转换相机三维空间到像素平面转换1. 3D点到相机平面转换2. 相机平面到像素平面转换涉及到单位的转换,和像素原点到相机平面原点…

webpack5 vue3同一仓库,不同命令切换项目

技术方案:手动输入不同的命令,启动不同项目。实现这种能力本篇文章是通过不同路由划分,进而实现不同项目的划分。所以简单来说就是通过输入不同命令行在webpack中找到不同项目的路由,进而打不同项目的包,实现项目隔离。…

PowerBI实战-制作带有同比及趋势线的双柱状图

一、引言 今天的PowerBI报表的制作相对有一点复杂,我们直接根据最终展示图来讲解: 可以看到,我们今天要制作的图像需要包括以下几点:时间维度的趋势、两种不同维度的数据对比、不同数据标签的展示、不同年份间环比的标签展示以及…

物联网智能网关配置教程:实现注塑机数据经基恩士PLC上传至云平台

一、项目背景随着制造业向智能化、信息化方向快速发展,注塑车间作为塑料制品制造的核心环节,面临着设备协议多样、数据孤岛严重、系统集成困难等问题。某大型注塑企业计划对其老旧车间进行数字化改造,实现设备数据采集、远程监控与MES系统对接…

【实战】预警算法--噪声添加机制

1. 背景 在多变量自联想预测或异常检测场景中,我们常使用带噪自编码器(Denoising AutoEncoder,DAE)来训练模型,使模型能够从带噪输入中重构原始数据。噪声的添加方式对训练效果、稳定性以及模型用途有显著影响。 2. 两…

ChromaDB探索

关于 ChromaDB、向量与 RAG 系统的核心知识问答总结 ​​Q1: ChromaDB 是什么?它在数据库领域中扮演什么角色?​​​​A:​​ ChromaDB 是一款开源的​​向量数据库​​。它的核心角色是专门为 AI 应用(如语义搜索、推荐系统、RAG&#xff09…

C# 基于halcon的视觉工作流-章33-矩状测量

C# 基于halcon的视觉工作流-章33-矩状测量 本章目标: 一、gen_measure_rectangle2准备提取垂直于矩形的直边; 二、measure_pos 提取垂直于矩形或环形弧的直线边缘; 三、measure_pairs提取垂直于矩形或环形弧长轴的直边对; 四、匹配…

Day05_苍穹外卖——Redis店铺营业状态设置

目录1.1 Redis简介1.2 Redis下载与安装1.2.1 Redis下载1.2.2 Redis安装1.3 Redis服务启动与停止1.3.1 服务启动命令1.3.2 客户端连接命令1.3.3 修改Redis配置文件1.3.4 Redis客户端图形工具2. Redis数据类型2.1 五种常用数据类型介绍2.2 各种数据类型特点3. Redis常用命令3.1 字…

双指针:字符串

题目&#xff1a;字符串 题目概述&#xff1a;找包含所有小写字母的最短字符串。 重点思路&#xff1a; right是 < len-1字符 - ‘26’转换成整形再判断&#xff08;写字符a也可以&#xff0c;更准确&#xff09;。 #include <iostream> #include <algorithm>…

HarmonyOS 应用开发深度实践:精通 Stage 模型与 UIAbility 生命周期

好的&#xff0c;请看这篇关于 HarmonyOS Stage 模型与 UIAbility 深度实践的技术文章。 HarmonyOS 应用开发深度实践&#xff1a;精通 Stage 模型与 UIAbility 生命周期 引言 随着 HarmonyOS 4、5 的广泛部署和 HarmonyOS NEXT (API 12) 的发布&#xff0c;华为的分布式操作系…

DEDECMS 小程序插件简介 2.0全新上线

网上有很多的dedecms的小程序插件&#xff0c;但是有的依赖他们第三方、有的需要一定php或sql基础、有的插件免费但是小程序源码价格昂贵&#xff0c;这也是促使我开发dedecms小程序插件的一大原因。2025年9月4日 dedecms小程序插件2.0版本正式上线&#xff0c;由于使用人数减少…

Flink 1.17.2 集群安装部署

Flink集群的安装 1. 集群规划 Ip host Server Note 192.168.10.101 node01 jobManager、TaskManagerRunner 老大和小弟服务 192.168.10.102 node02 TaskManagerRunner 小弟 192.168.10.103 node03 TaskManagerRunner 小弟 注意&#xff1a;本次使用jdk-1.8.0…

[vue.js] 树形结点多选框选择

vue.js前端代码&#xff1a; <template><div><el-tree:data"treeData"node-key"id"show-checkboxref"tree"check-change"handleCheckChange"/><el-button click"getSelectedNodes">获取选中的节点&…

Web 服务器基本工作流程

这是一个关于 ​​Web 服务器基本工作流程​​ 的全面解释。我们以最经典的 ​​客户端-服务器-后端​​ 三层架构为例&#xff0c;并结合你之前遇到的 Nginx 场景进行说明。​​核心角色​​​​客户端 (Client)​​&#xff1a; 通常是 ​​Web 浏览器​​ (Chrome, Firefox)…