Skip to main content
Visitor II
August 11, 2025
Question

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

  • August 11, 2025
  • 5 replies
  • 466 views

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

    This topic has been closed for replies.

    5 replies

    Technical Moderator
    August 12, 2025
    Visitor II
    August 12, 2025

    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

     

    Technical Moderator
    August 12, 2025
    Visitor II
    August 13, 2025

    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

    Visitor II
    August 14, 2025

    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 */

     

     

     

    Graduate II
    August 14, 2025

    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.

    Visitor II
    August 14, 2025

    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