硬汉嵌入式论坛

 找回密码
 立即注册
查看: 760|回复: 6
收起左侧

[STM32H7] STM32H7在多块方式读写EMMC的时候出错

[复制链接]

3

主题

16

回帖

25

积分

新手上路

积分
25
发表于 2024-8-19 10:22:20 | 显示全部楼层 |阅读模式
各位专家大家好,我在使用EMMC的读写,单块读写是没有问题的,但是多块读写时候就出错了,我跟踪程序,发现是发送多块读的命令后就超时了,采用硬汉的DMA方式的EMC读写还是有问题,后来我不得不把读写程序修改为如下,多块读写的时候强制修改为单块读写测试能正常运行,感觉也不稳定,请问各位专家,我的问题出在哪里哈?万分感谢。:


DRESULT USER_read (
        BYTE pdrv,      /* Physical drive nmuber to identify the drive */
        BYTE *buff,     /* Data buffer to store read data */
        DWORD sector,   /* Sector address in LBA */
        UINT count      /* Number of sectors to read */
)
{
  /* USER CODE BEGIN READ */
#if 1
        mmc_res=0;
        for(int i=0;i<count;i++)
        {
                mmc_res|=HAL_MMC_ReadBlocks(&hmmc1, (uint8_t *)(buff+i*512), sector+i, 1, 0xffff);
                HAL_Delay(1);
         if ( mmc_res!= HAL_OK)
    {
      return RES_ERROR;
    }
}
  return RES_OK;
#else
    if (HAL_MMC_ReadBlocks(&hmmc1, (uint8_t *)buff, sector, count, 0xffff) == HAL_OK)
  {
    return RES_OK;
  }
  return RES_ERROR;
#endif
  /* USER CODE END READ */
}



DRESULT USER_write (
        BYTE pdrv,          /* Physical drive nmuber to identify the drive */
        const BYTE *buff,   /* Data to be written */
        DWORD sector,       /* Sector address in LBA */
        UINT count          /* Number of sectors to write */
)
{
  /* USER CODE BEGIN WRITE */
  /* USER CODE HERE */
#if 1
        mmc_res=0;
        for(int i=0;i<count;i++)
        {
                mmc_res|=HAL_MMC_WriteBlocks(&hmmc1, (uint8_t *)(buff+i*512), sector+i, 1, 0xffff);
                HAL_Delay(1);
         if ( mmc_res!= HAL_OK)
    {
      return RES_ERROR;
    }
}
  return RES_OK;
#else
                mmc_res=HAL_MMC_WriteBlocks(&hmmc1, (uint8_t *)buff, sector, count, 0xffff);
         if ( mmc_res== HAL_OK)
    {
      return RES_OK;
    }

  return RES_ERROR;
#endif
   
  /* USER CODE END WRITE */
}

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-8-19 15:30:31 | 显示全部楼层
eMMC的速度和线宽调节测试过没。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-8-19 15:30:57 | 显示全部楼层
eMMC的速度和线宽调节测试过没。
回复

使用道具 举报

3

主题

16

回帖

25

积分

新手上路

积分
25
 楼主| 发表于 2024-8-20 13:56:05 | 显示全部楼层
特意加了一句修改成4BIT,然后将速度DIV又原来的3修改为15,还是只能单BLOCK读写, 我想请问下硬汉,是否需要设置某些参数才能支持多BLOCK读写呢?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-8-21 12:29:40 | 显示全部楼层
qq302011 发表于 2024-8-20 13:56
特意加了一句修改成4BIT,然后将速度DIV又原来的3修改为15,还是只能单BLOCK读写, 我想请问下硬汉,是否需 ...

不需要特别参数,就跟SD是一样的,只是eMMC使用的XXX_MMC.c文件
回复

使用道具 举报

3

主题

16

回帖

25

积分

新手上路

积分
25
 楼主| 发表于 2024-8-27 14:03:11 | 显示全部楼层
我是这样使用的啊,代码如下,我现在读写的时候只能一块一块读,使用多块就会发送命令后超时,请专家帮我指导指导哈。
/* USER CODE BEGIN Header */
/**
******************************************************************************
  * @file    user_diskio.c
  * @brief   This file includes a diskio driver skeleton to be completed by the user.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 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 */

#ifdef USE_OBSOLETE_USER_CODE_SECTION_0
/*
* Warning: the user section 0 is no more in use (starting from CubeMx version 4.16.0)
* To be suppressed in the future.
* Kept to ensure backward compatibility with previous CubeMx versions when
* migrating projects.
* User code previously added there should be copied in the new user sections before
* the section contents can be deleted.
*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
#endif

/* USER CODE BEGIN DECL */

/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include "ff_gen_drv.h"

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

/* Private variables ---------------------------------------------------------*/
/* Disk status */
#define MMC_DEFAULT_BLOCK_SIZE  (512)
static volatile DSTATUS Stat = STA_NOINIT;
static volatile int  mmc_res=0;
extern MMC_HandleTypeDef hmmc1;
/* USER CODE END DECL */

/* Private function prototypes -----------------------------------------------*/
DSTATUS USER_initialize (BYTE pdrv);
DSTATUS USER_status (BYTE pdrv);
DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
#if _USE_WRITE == 1
  DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
  DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff);
#endif /* _USE_IOCTL == 1 */

Diskio_drvTypeDef  USER_Driver =
{
  USER_initialize,
  USER_status,
  USER_read,
#if  _USE_WRITE
  USER_write,
#endif  /* _USE_WRITE == 1 */
#if  _USE_IOCTL == 1
  USER_ioctl,
#endif /* _USE_IOCTL == 1 */
};

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Initializes a Drive
  * @param  pdrv: Physical drive number (0..)
  * @retval DSTATUS: Operation status
  */
DSTATUS USER_initialize (
        BYTE pdrv           /* Physical drive nmuber to identify the drive */
)
{
  /* USER CODE BEGIN INIT */
          //if(HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)
                {
      Stat &= ~STA_NOINIT;
    }
    return RES_OK;
  /* USER CODE END INIT */
}

/**
  * @brief  Gets Disk Status
  * @param  pdrv: Physical drive number (0..)
  * @retval DSTATUS: Operation status
  */
DSTATUS USER_status (
        BYTE pdrv       /* Physical drive number to identify the drive */
)
{
  /* USER CODE BEGIN STATUS */
        Stat = STA_NOINIT;
         if(HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)
                {
      Stat &= ~STA_NOINIT;
    }
    return Stat;
  /* USER CODE END STATUS */
}

/**
  * @brief  Reads Sector(s)
  * @param  pdrv: Physical drive number (0..)
  * @param  *buff: Data buffer to store read data
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to read (1..128)
  * @retval DRESULT: Operation result
  */
DRESULT USER_read (
        BYTE pdrv,      /* Physical drive nmuber to identify the drive */
        BYTE *buff,     /* Data buffer to store read data */
        DWORD sector,   /* Sector address in LBA */
        UINT count      /* Number of sectors to read */
)
{
  /* USER CODE BEGIN READ */
#if 1
        mmc_res=0;
        for(int i=0;i<count;i++)
        {
                mmc_res|=HAL_MMC_ReadBlocks(&hmmc1, (uint8_t *)(buff+i*512), sector+i, 1, 0xffff);
                HAL_Delay(1);
         if ( mmc_res!= HAL_OK)
    {
      return RES_ERROR;
    }
}
  return RES_OK;
#else
    if (HAL_MMC_ReadBlocks(&hmmc1, (uint8_t *)buff, sector, count, 0xffff) == HAL_OK)
  {
    return RES_OK;
  }
  return RES_ERROR;
#endif
  /* USER CODE END READ */
}

/**
  * @brief  Writes Sector(s)
  * @param  pdrv: Physical drive number (0..)
  * @param  *buff: Data to be written
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to write (1..128)
  * @retval DRESULT: Operation result
  */
#if _USE_WRITE == 1
DRESULT USER_write (
        BYTE pdrv,          /* Physical drive nmuber to identify the drive */
        const BYTE *buff,   /* Data to be written */
        DWORD sector,       /* Sector address in LBA */
        UINT count          /* Number of sectors to write */
)
{
  /* USER CODE BEGIN WRITE */
  /* USER CODE HERE */
#if 1
        mmc_res=0;
        for(int i=0;i<count;i++)
        {
                mmc_res|=HAL_MMC_WriteBlocks(&hmmc1, (uint8_t *)(buff+i*512), sector+i, 1, 0xffff);
                HAL_Delay(1);
         if ( mmc_res!= HAL_OK)
    {
      return RES_ERROR;
    }
}
  return RES_OK;
#else
                mmc_res=HAL_MMC_WriteBlocks(&hmmc1, (uint8_t *)buff, sector, count, 0xffff);
         if ( mmc_res== HAL_OK)
    {
      return RES_OK;
    }

  return RES_ERROR;
#endif
   
  /* USER CODE END WRITE */
}
#endif /* _USE_WRITE == 1 */

/**
  * @brief  I/O control operation
  * @param  pdrv: Physical drive number (0..)
  * @param  cmd: Control code
  * @param  *buff: Buffer to send/receive control data
  * @retval DRESULT: Operation result
  */
#if _USE_IOCTL == 1
DRESULT USER_ioctl (
        BYTE pdrv,      /* Physical drive nmuber (0..) */
        BYTE cmd,       /* Control code */
        void *buff      /* Buffer to send/receive control data */
)
{
  /* USER CODE BEGIN IOCTL */
  DRESULT res = RES_ERROR;
  HAL_MMC_CardInfoTypeDef CardInfo;

  if (Stat & STA_NOINIT) return RES_NOTRDY;

  switch (cmd)
  {
  /* Make sure that no pending write process */
  case CTRL_SYNC :
    res = RES_OK;
    break;

  /* Get number of sectors on the disk (DWORD) */
  case GET_SECTOR_COUNT :
    HAL_MMC_GetCardInfo(&hmmc1,&CardInfo);
    *(DWORD*)buff = CardInfo.LogBlockNbr;
    res = RES_OK;
    break;

  /* Get R/W sector size (WORD) */
  case GET_SECTOR_SIZE :
    HAL_MMC_GetCardInfo(&hmmc1,&CardInfo);
    *(WORD*)buff = CardInfo.LogBlockSize;
    res = RES_OK;
    break;

  /* Get erase block size in unit of sector (DWORD) */
  case GET_BLOCK_SIZE :
    HAL_MMC_GetCardInfo(&hmmc1,&CardInfo);
    *(DWORD*)buff = CardInfo.LogBlockSize / MMC_DEFAULT_BLOCK_SIZE;
    res = RES_OK;
    break;

  default:
    res = RES_PARERR;
  }

  return res;
  /* USER CODE END IOCTL */
}
#endif /* _USE_IOCTL == 1 */

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-8-28 09:01:45 | 显示全部楼层
qq302011 发表于 2024-8-27 14:03
我是这样使用的啊,代码如下,我现在读写的时候只能一块一块读,使用多块就会发送命令后超时,请专家帮我指 ...

那也行,可以单块读写多次也可以。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-4-29 05:20 , Processed in 0.322002 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表