Skip to main content
Explorer II
January 17, 2025
Question

Programming an STM32H7 for Samsung eMMC Support

  • January 17, 2025
  • 3 replies
  • 1615 views

Hello,

I've just received my custom PCB with an STM32H743VIT6 MCU.

It has a Samsung eMMC connected to the SDMMC1 interface (MMC 8 Bits Wide Bus) :

yaxsomo_0-1737130265822.png

(I'll link the eMMC datasheet below.)

I'm encountering some issues while initializing the device with the MX_SDMMC1_MMC_Init function. 
More particularly it seems to be stuck in the HAL_MMC_InitCard function, on this block : 

/* Card initialization */

errorstate = MMC_InitCard(hmmc);

if (errorstate != HAL_MMC_ERROR_NONE)

{

hmmc->State = HAL_MMC_STATE_READY;

hmmc->ErrorCode |= errorstate;

return HAL_ERROR;

}

 

When i launch a debug session it seems to freeze on this block :

/* Get CSD parameters */

if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)

{

return hmmc->ErrorCode;

}

 


Here's the variables states at this breakpoint :

yaxsomo_1-1737130504759.pngyaxsomo_2-1737130510135.pngyaxsomo_3-1737130514249.png

The data does not seem coherent. Am I missing something here ?
For the configuration of the SDMMC1 interface i setted the Clock at 50MHz on the Clock Configuration, and a Divide Factor of 8 (tried 0, 5 and 6 but have the same result) :

yaxsomo_4-1737130600566.pngyaxsomo_5-1737130627953.png

Could someone help me solve this issue?

 

    This topic has been closed for replies.

    3 replies

    Visitor II
    January 18, 2025

    Just questions and thoughts:
    - why do you have 5pF caps there?
    - why do you have everywhere pull-ups? (really needed?)
    - are you sure to have an external eMMC chip for 3V3 logic levels?
      (there are different versions, for different "interface power")

    As I understand (eMMC, SD card...):
    - the initial config phase is just a simple, single lane (like SPI) access
    - just after this was successful - the config keeps going by checking capabilities (eMMC registers), such as:
      - voltage level for the signaling - yes! it can be "negotiated" that chips wants to get with lower voltage and signal levels

      - 1bit, 4bit, 8bit capabilities

    In which phase do you stuck? (e.g. reading fundamental status registers, capability registers)?

    I would assume that your chip wants to go down on power supply level, signal voltage level but you do not "follow" the chip capabilities(even assuming you could read the very first eMMC register): you keep driving always 3V3, never lowering VDD... Maybe the chip "tells" you (or it fails to respond properly) that it does not want to stay all the time at 3V3, instead it wants to go with lower voltages.

    What do you get from eMMC chip (on status and capability registers read)?

    yaxsomoAuthor
    Explorer II
    January 18, 2025

    @tjaekel wrote:

    Just questions and thoughts:
    - why do you have 5pF caps there?
    - why do you have everywhere pull-ups? (really needed?)

    As per JEDEC standard, i applied what I learned from the standard no.JESD84-B50 :

    yaxsomo_0-1737194885616.png

    So yes, pull-ups are indeed needed, and capacitors also.

     


    @tjaekel wrote:


    - are you sure to have an external eMMC chip for 3V3 logic levels?
      (there are different versions, for different "interface power")

     


    For this eMMC model, i can totally power it with only 3.3V on both VCC and VCCQ :

    yaxsomo_1-1737195140926.png

    The only thing is that, as per JEDEC standard, HS200 and HS400 will not be supported.


    @tjaekel wrote:

    As I understand (eMMC, SD card...):
    - the initial config phase is just a simple, single lane (like SPI) access
    - just after this was successful - the config keeps going by checking capabilities (eMMC registers), such as:
      - voltage level for the signaling - yes! it can be "negotiated" that chips wants to get with lower voltage and signal levels

      - 1bit, 4bit, 8bit capabilities

    In which phase do you stuck? (e.g. reading fundamental status registers, capability registers)?

    I would assume that your chip wants to go down on power supply level, signal voltage level but you do not "follow" the chip capabilities(even assuming you could read the very first eMMC register): you keep driving always 3V3, never lowering VDD... Maybe the chip "tells" you (or it fails to respond properly) that it does not want to stay all the time at 3V3, instead it wants to go with lower voltages.

    What do you get from eMMC chip (on status and capability registers read)?


    I don't think it's a voltage level issue. Here's the execution of the commands CMD2, CMD3, CMD9 and CMD12 : 

    For CMD2 : 

     

     /* Send CMD2 ALL_SEND_CID */
     errorstate = SDMMC_CmdSendCID(hmmc->Instance);
     if (errorstate != HAL_MMC_ERROR_NONE)
     {
     return errorstate;
     }
     else
     {
     /* Get Card identification number data */
     hmmc->CID[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
     hmmc->CID[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
     hmmc->CID[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
     hmmc->CID[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
     }

     

    Here's the result on the variables state : 

    yaxsomo_2-1737198179170.png

    (Seems correct to me, as it corresponds to the 128-bit CID register)

     

    For CMD3 : 

     

     /* Send CMD3 SET_REL_ADDR with RCA = 2 (should be greater than 1) */
     /* MMC Card publishes its RCA. */
     errorstate = SDMMC_CmdSetRelAddMmc(hmmc->Instance, mmc_rca);
     if (errorstate != HAL_MMC_ERROR_NONE)
     {
     return errorstate;
     }
    
     /* Get the MMC card RCA */
     hmmc->MmcCard.RelCardAdd = mmc_rca;

     

    Here's the result : 

    yaxsomo_3-1737198259791.png

    RCA seems valid, as it requires to be greater than 1, as per MMC protocol.

     

    For CMD9 : 

     

     /* Send CMD9 SEND_CSD with argument as card's RCA */
     errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
     if (errorstate != HAL_MMC_ERROR_NONE)
     {
     return errorstate;
     }
     else
     {
     /* Get Card Specific Data */
     hmmc->CSD[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
     hmmc->CSD[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
     hmmc->CSD[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
     hmmc->CSD[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
     }

     

    I get this result : 

    yaxsomo_4-1737198346639.png

     I don't know how to decode this thing, but it does not seem too bad.

     

    For CMD7 : 

     

     /* Select the Card */
     errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
     if (errorstate != HAL_MMC_ERROR_NONE)
     {
     return errorstate;
     }
    
    here's the function definition : 
    
    uint32_t SDMMC_CmdSelDesel(SDMMC_TypeDef *SDMMCx, uint32_t Addr)
    {
     SDMMC_CmdInitTypeDef sdmmc_cmdinit;
     uint32_t errorstate;
    
     /* Send CMD7 SDMMC_SEL_DESEL_CARD */
     sdmmc_cmdinit.Argument = (uint32_t)Addr;
     sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEL_DESEL_CARD;
     sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
     sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
     sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
     (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
    
     /* Check for error conditions */
     errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SEL_DESEL_CARD, SDMMC_CMDTIMEOUT);
    
     return errorstate;
    }

     

    I get this result : 

    yaxsomo_5-1737198454702.png

    And seems also good to me.

     

    The issue lies withing the MMC_ReadExtCSD function, particularly in the polling loop that waits for the SDMMC flags (RXOVERR, DCRCFAIL, DTIMEOUT, DATAEND) to be set, but the loop never exits : 

     

     /* Get CSD parameters */ --> The issues starts here
     if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
     {
     return hmmc->ErrorCode;
     }
     // --> We never get to this point
     /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 
     errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
     if (errorstate != HAL_MMC_ERROR_NONE)
     {
     hmmc->ErrorCode |= errorstate;
     }

     

    On the HAL_MMC_GetCardCSD, :

     

    /**
     * @brief Returns information the information of the card which are stored on
     * the CSD register.
     * @PAram hmmc: Pointer to MMC handle
     * @PAram pCSD: Pointer to a HAL_MMC_CardCSDTypeDef structure that
     * contains all CSD register parameters
     * @retval HAL status
     */
    HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
    {
     uint32_t block_nbr = 0;
    
     pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U);
    
     pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U);
    
     pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U);
    
     pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U);
    
     pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U);
    
     pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU);
    
     pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U);
    
     pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U);
    
     pCSD->PartBlockRead = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U);
    
     pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U);
    
     pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U);
    
     pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U);
    
     pCSD->Reserved2 = 0U; /*!< Reserved */
    
     if (MMC_ReadExtCSD(hmmc, &block_nbr, 212, 0x0FFFFFFFU) != HAL_OK) /* Field SEC_COUNT [215:212] */ --> Here's the problematic function
     {
     return HAL_ERROR;
     }
    
     if (hmmc->MmcCard.CardType == MMC_LOW_CAPACITY_CARD)
     {
     pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U));
    
     pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U);
    
     pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U);
    
     pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U);
    
     pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U);
    
     pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U);
    
     hmmc->MmcCard.BlockNbr = (pCSD->DeviceSize + 1U) ;
     hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
     hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
    
     hmmc->MmcCard.LogBlockNbr = (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U);
     hmmc->MmcCard.LogBlockSize = 512U;
     }
     else if (hmmc->MmcCard.CardType == MMC_HIGH_CAPACITY_CARD)
     {
     hmmc->MmcCard.BlockNbr = block_nbr;
     hmmc->MmcCard.LogBlockNbr = hmmc->MmcCard.BlockNbr;
     hmmc->MmcCard.BlockSize = 512U;
     hmmc->MmcCard.LogBlockSize = hmmc->MmcCard.BlockSize;
     }
     else
     {
     /* Clear all the static flags */
     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
     hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
     hmmc->State = HAL_MMC_STATE_READY;
     return HAL_ERROR;
     }
    
     pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U);
    
     pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U);
    
     pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU);
    
     pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U);
    
     pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U);
    
     pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U);
    
     pCSD->MaxWrBlockLen = (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U);
    
     pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U);
    
     pCSD->Reserved3 = 0;
    
     pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U);
    
     pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U);
    
     pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U);
    
     pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U);
    
     pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U);
    
     pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U);
    
     pCSD->ECC = (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U);
    
     pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U);
    
     pCSD->Reserved4 = 1;
    
     return HAL_OK;
    }

     

    There's the function while loop: 

     

     /* Poll on SDMMC flags */
     while (!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT |
     SDMMC_FLAG_DATAEND))
     {
     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF))
     {
     /* Read data from SDMMC Rx FIFO */
     for (count = 0U; count < 8U; count++)
     {
     tmp_data = SDMMC_ReadFIFO(hmmc->Instance);
     /* eg : SEC_COUNT : FieldIndex = 212 => i+count = 53 */
     /* DEVICE_TYPE : FieldIndex = 196 => i+count = 49 */
     if ((i + count) == ((uint32_t)FieldIndex / 4U))
     {
     *pFieldData = tmp_data;
     }
     }
     i += 8U;
     }
    
     if (((HAL_GetTick() - tickstart) >= Timeout) || (Timeout == 0U))
     {
     /* Clear all the static flags */
     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
     hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
     hmmc->State = HAL_MMC_STATE_READY;
     return HAL_TIMEOUT;
     }
     }

     

     

     

    And I'm not sure why it's stuck there

     

     

    Explorer
    October 14, 2025

    If you've made any progress, an update here would be greatly appreciated. 

    I'm having an issue that appears to be identical, except with an STM32N657. I'm getting stuck in this same loop, and like you also seeing that my eMMC is responding sensibly to the commands prior to trying to retrieve the extended CSD.

     

    yaxsomoAuthor
    Explorer II
    January 19, 2025

    Anyone who can help me figure out the issue ?

    Visitor II
    January 6, 2026

    Hi! Has this issue been resolved? If so, could you share how it was fixed?
    I’m using a THGBMJG8C2LBAIL eMMC on an STM32U385RGI and I’m running into the exact same problem.