cancel
Showing results for 
Search instead for 
Did you mean: 

Need Disk i/o.c for mmc flash for FATFS

KumarMayank99
Associate II

Hi all,

I am using the MTFC8GAMALNA-AAT 8GB flash memory via SDMMC1, operating in MMC 4-bit wide bus mode, along with FATFS (M7). I now require the diskio.c file. Kindly provide it, or if you have any related example code, please share that as well. Please note that I do not want to use DMA or an RTOS for this implementation.

Thanks

7 REPLIES 7
Saket_Om
ST Employee

Hello @KumarMayank99 

Please refer to the example below:

Projects/STM32H743I-EVAL/Applications/FatFs/FatFs_uSD_Standalone

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
KumarMayank99
Associate II

Hi @Saket_Om ,

Thank you for your response.

I would like to ask if you have a ready-made diskio.c  implementation that supports MMC in 4-bit mode. If available, I would greatly appreciate it if you could share the file or point me in the right direction.

Best regards,

Mayank

 

Hello @KumarMayank99 

The example below use SDMMC in 4 bit mode with FATFS.

STM32CubeH7RS/Projects/STM32H7S78-DK/Applications/FatFs/FatFs_uSD_Standalone at main · STMicroelectronics/STM32CubeH7RS · GitHub

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
KumarMayank99
Associate II

Hi @Saket_Om,

Thank you for your response.

I checked and i found that this is  for SD 4 bits mode bus but  i want mmc 4 bits wide bus.

KumarMayank99_0-1755062932684.png

 

Best regards,

Mayank

KumarMayank99
Associate II

Hi @Saket_Om

Below is my user_diskio.c file please chcek ones is it correct or need to modify .

 

 

 

/* Includes ------------------------------------------------------------------*/

#include <string.h>

#include "ff_gen_drv.h"

 

 

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

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

 

/* Private variables ---------------------------------------------------------*/

/* Disk status */

static volatile DSTATUS Stat = STA_NOINIT;

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)

{

Stat = STA_NOINIT;

 

if (pdrv != 0)

return Stat;

 

if (HAL_MMC_InitCard(&hmmc1) == HAL_OK)

{

// Configure 4-bit bus width

if (HAL_MMC_ConfigWideBusOperation(&hmmc1, SDMMC_BUS_WIDE_4B) == HAL_OK)

{

Stat &= ~STA_NOINIT; // Clear NOINIT flag

}

}

 

return Stat;

}

 

 

/**

* @brief Gets Disk Status

* @param pdrv: Physical drive number (0..)

* @retval DSTATUS: Operation status

*/

DSTATUS USER_status(BYTE pdrv)

{

if (pdrv != 0)

return STA_NOINIT;

if (HAL_MMC_GetCardState(&hmmc1)==HAL_MMC_CARD_TRANSFER)

return RES_OK;

return STA_NOINIT;

}

 

 

/**

* @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, BYTE *buff, DWORD sector, UINT count)

{

if (pdrv != 0 || !count)

return RES_PARERR;

if (Stat & STA_NOINIT)

return RES_NOTRDY;

if (HAL_MMC_ReadBlocks(&hmmc1, buff, sector, count, HAL_MAX_DELAY) == HAL_OK)

{

// Wait until card is in transfer state

while (HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER);

return RES_OK;

}

return RES_ERROR;

}

 

 

/**

* @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, const BYTE *buff, DWORD sector, UINT count)

{

if (pdrv != 0 || !count)

return RES_PARERR;

if (Stat & STA_NOINIT)

return RES_NOTRDY;

if (HAL_MMC_WriteBlocks(&hmmc1, (uint8_t*)buff, sector, count, HAL_MAX_DELAY) == HAL_OK)

{

while (HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER);

return RES_OK;

}

return RES_ERROR;

}

 

#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, BYTE cmd, void *buff)

{

DRESULT res = RES_ERROR;

HAL_MMC_CardInfoTypeDef CardInfo;

if (Stat & STA_NOINIT)

return RES_NOTRDY;

if (pdrv != 0)

return RES_PARERR;

switch (cmd)

{

case CTRL_SYNC:

res = RES_OK;

break;

case GET_SECTOR_COUNT:

HAL_MMC_GetCardInfo(&hmmc1, &CardInfo);

*(DWORD*)buff = CardInfo.LogBlockNbr;

res = RES_OK;

break;

case GET_SECTOR_SIZE:

HAL_MMC_GetCardInfo(&hmmc1, &CardInfo);

*(WORD*)buff = CardInfo.LogBlockSize;

res = RES_OK;

break;

case GET_BLOCK_SIZE:

*(DWORD*)buff = 1; // Usually 1 for MMC unless otherwise specified

res = RES_OK;

break;

default:

res = RES_PARERR;

}

return res;

}

 

#endif /* _USE_IOCTL == 1 */

 

 

 

Use the code pasting tool via </> icon rather than inline unformatted wall of text.

Should be an MMC example within some releases of H745I-DISCO board.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
KumarMayank99
Associate II

Hi @Tesla DeLorean @Saket_Om 

Thank you for your response.

I am currently using the STM32H755BIT3 microcontroller.

Could you please review my user_diskio.c file to ensure it is correctly implemented for this MCU? Let me know if any modifications are needed.

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    user_diskio.c
  * @brief   This file includes a diskio driver aligned with STM reference logic.
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include "ff_gen_drv.h"
#include "main.h" // In case needed for definitions like HAL_MAX_DELAY

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define MMC_DEFAULT_BLOCK_SIZE 512
#define MMC_TIMEOUT HAL_MAX_DELAY

/* Private variables ---------------------------------------------------------*/
static volatile DSTATUS Stat = STA_NOINIT;
extern MMC_HandleTypeDef hmmc1;

/* Private function prototypes -----------------------------------------------*/
static DSTATUS USER_CheckStatus(BYTE pdrv);
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
#if _USE_IOCTL == 1
DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void *buff);
#endif

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

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

static DSTATUS USER_CheckStatus(BYTE pdrv)
{
  Stat = STA_NOINIT;

  if (pdrv != 0)
    return Stat;

  if (HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)
    Stat &= ~STA_NOINIT;

  return Stat;
}

/**
  * @brief  Initializes a Drive
  * @param  pdrv: Physical drive number (0..)
  * @retval DSTATUS: Operation status
  */
DSTATUS USER_initialize(BYTE pdrv)
{
  Stat = STA_NOINIT;

  if (pdrv != 0)
    return Stat;

  if (HAL_MMC_InitCard(&hmmc1) == HAL_OK)
  {
    if (HAL_MMC_ConfigWideBusOperation(&hmmc1, SDMMC_BUS_WIDE_4B) == HAL_OK)
    {
      Stat = USER_CheckStatus(pdrv);
    }
  }

  return Stat;
}

/**
  * @brief  Gets Disk Status
  * @param  pdrv: Physical drive number (0..)
  * @retval DSTATUS: Operation status
  */
DSTATUS USER_status(BYTE pdrv)
{
  return USER_CheckStatus(pdrv);
}

/**
  * @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, BYTE *buff, DWORD sector, UINT count)
{
  if ((pdrv != 0) || !count)
    return RES_PARERR;

  if (Stat & STA_NOINIT)
    return RES_NOTRDY;

  if (HAL_MMC_ReadBlocks(&hmmc1, buff, sector, count, MMC_TIMEOUT) == HAL_OK)
  {
    while (HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER);
    return RES_OK;
  }

  return RES_ERROR;
}

/**
  * @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, const BYTE *buff, DWORD sector, UINT count)
{
  if ((pdrv != 0) || !count)
    return RES_PARERR;

  if (Stat & STA_NOINIT)
    return RES_NOTRDY;

  if (HAL_MMC_WriteBlocks(&hmmc1, (uint8_t *)buff, sector, count, MMC_TIMEOUT) == HAL_OK)
  {
    while (HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER);
    return RES_OK;
  }

  return RES_ERROR;
}
#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, BYTE cmd, void *buff)
{
  DRESULT res = RES_ERROR;
  HAL_MMC_CardInfoTypeDef CardInfo;

  if (Stat & STA_NOINIT)
    return RES_NOTRDY;

  if (pdrv != 0)
    return RES_PARERR;

  switch (cmd)
  {
    case CTRL_SYNC:
      res = RES_OK;
      break;

    case GET_SECTOR_COUNT:
      HAL_MMC_GetCardInfo(&hmmc1, &CardInfo);
      *(DWORD *)buff = CardInfo.LogBlockNbr;
      res = RES_OK;
      break;

    case GET_SECTOR_SIZE:
      HAL_MMC_GetCardInfo(&hmmc1, &CardInfo);
      *(WORD *)buff = CardInfo.LogBlockSize;
      res = RES_OK;
      break;

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

  while (HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER);

  return res;
}
#endif /* _USE_IOCTL == 1 */

Regard,

Mayank