2025-08-11 6:06 AM
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
2025-08-12 3:32 AM
Hello @KumarMayank99
Please refer to the example below:
Projects/STM32H743I-EVAL/Applications/FatFs/FatFs_uSD_Standalone
2025-08-12 4:55 AM
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
2025-08-12 6:15 AM
Hello @KumarMayank99
The example below use SDMMC in 4 bit mode with FATFS.
2025-08-12 10:29 PM
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.
Best regards,
Mayank
2025-08-14 2:02 AM
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 */
2025-08-14 3:12 AM
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.
2025-08-14 4:04 AM
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