cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H755 SDMMC1 with DMA or IT

TOlli
Senior

Hi,

I've been trying to get the SDMM1 working on a custom board with an eMMC (ISSI 32GB).

Are there any working examples from ST that verifies you have actually tested the MMC side of the HAL library to be working? @Imen DAHMEN​ 

I am able to get the CSD and CID information from the chip. I see a correct sequence of CMD and R1 from the chip when asking for the data, but I see nothing on my buffers.

Things I've done:

  • Lowered the bus width to 1 bit (max is 4)
  • Enabled HW flow control (does not work without this either)
  • Lowered the clock signal to 4MHz
  • Try using both DMA and IT operations from the HAL library
  • My buffers have been assigned to D1 RAM
  • I have disabled MPU
  • I have disabled the cache functions

I'm using the 1.8.0 version of the HAL library for the H7, and I've reviewed the examples (FatFS etc.) from the H7 series that use DMA with SD, but these do not help since the functions used are different. My call structure is identical to the examples:

	for(int i = 0; i < 512; i++) {
		txBuffer[i] = i % 255;
		rxBuffer[i] = 0;
	}
 
	if(HAL_MMC_Erase(&hmmc1, 0x1000, 0x5001) != HAL_OK) {
		Error_Handler();
	}
 
	while(HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER) {
		HAL_Delay(100);
	}
//
//	if(HAL_MMC_WriteBlocks_DMA(&hmmc1, txBuffer, 0x5000, 1) != HAL_OK) {
//		Error_Handler();
//	}
 
	if(HAL_MMC_WriteBlocks_IT(&hmmc1, txBuffer, 0x5000, 1) != HAL_OK) {
		Error_Handler();
	}
 
	while(HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER) {
		HAL_Delay(100);
	}
 
//	if(HAL_MMC_ReadBlocks_DMA(&hmmc1, rxBuffer, 0x5000, 1) != HAL_OK) {
//		;
//	}
 
	if(HAL_MMC_ReadBlocks_IT(&hmmc1, rxBuffer, 0x5000, 1) != HAL_OK) {
		;
	}

I have monitored the bus and I do see the reply from the bus but there is no data in the buffers.

The buffers are global variables.

My system uses FreeRTOS and the above calls are made from a task, before it enters the for(;;)-part.

I have reviewed the document AN5200 "Getting started with SDMMC on the H7", but I don't see what else I'm supposed to do.

I have not enabled any DMAs from the CubeMX side, since SDMMC is supposedly using its internal DMA for the transactions.

Any help will be appreciated, even if you just have a minimum working example aside from the abysmal HAL examples.

Best regards

4 REPLIES 4
TOlli
Senior

I read through the AN5200. Again. My question is: Do I need to configure that IDMA/MDMA is used or does the HAL layer do the magic for me?

Do I need to touch the MDMA configuration to provide a channel in the .ioc file? I don't see this being done in the examples, so I'm guessing no.

I'm looking at the examples for STM32H745I-DISCO/Examples/MMC/MMC_ReadWrite_DMA and I don't see any configuration for the MDMA, all I see are

HAL_MMC_WriteBlocks_DMA(arguments);

HAL_MMC_ReadBlocks_DMA(arguments);

and it just works apparently.

Am I missing something here with the configuration?

@Imen DAHMEN​ 

TOlli
Senior

And I went back again into the HAL driver.

Does the HAL driver actually support 4 bit wide bus or not?

/**
  * @brief  Initializes the mmc card.
  * @param  hmmc: Pointer to MMC handle
  * @retval MMC Card error state
  */
static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
{
  HAL_MMC_CardCSDTypeDef CSD;
  uint32_t errorstate;
  uint16_t mmc_rca = 1U;
  MMC_InitTypeDef Init;
 
  /* Check the power State */
  if(SDMMC_GetPowerState(hmmc->Instance) == 0U)
  {
    /* Power off */
    return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
  }
 
  /* 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);
  }
 
  /* Send CMD3 SET_REL_ADDR with argument 0 */
  /* MMC Card publishes its RCA. */
  errorstate = SDMMC_CmdSetRelAdd(hmmc->Instance, &mmc_rca);
  if(errorstate != HAL_MMC_ERROR_NONE)
  {
    return errorstate;
  }
 
  /* Get the MMC card RCA */
  hmmc->MmcCard.RelCardAdd = mmc_rca;
 
  /* 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);
  }
 
  /* Get the Card Class */
  hmmc->MmcCard.Class = (SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2) >> 20U);
 
   /* Select the Card */
  errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
  if(errorstate != HAL_MMC_ERROR_NONE)
  {
    return errorstate;
  }
 
  /* Get CSD parameters */
  if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
  {
    return hmmc->ErrorCode;
  }
 
  /* 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;
  }
 
  /* Configure the SDMMC peripheral */
  Init.ClockEdge           = hmmc->Init.ClockEdge;
  Init.ClockPowerSave      = hmmc->Init.ClockPowerSave;
  Init.BusWide             = SDMMC_BUS_WIDE_1B;  // <- Why is this forced???
  Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
  Init.ClockDiv            = hmmc->Init.ClockDiv;
  (void)SDMMC_Init(hmmc->Instance, Init);
 
  /* All cards are initialized */
  return HAL_MMC_ERROR_NONE;
}

Check line 87: why is this value forced to 1B? Do I need to rewrite the HAL driver to get 4B support, or is this something ST is going to provide at some point?

0693W000004IfrhQAC.jpg

Best regards

TDK
Guru

One bit mode is forced as eMMC starts in one bit mode. You can switch to 4- or 8- bit mode afterwards. CubeMX will generate code that does this for you, although the eMMC support with HAL is not great.

If you feel a post has answered your question, please click "Accept as Solution".

Hi TDK,

I noticed that the init sequence is done correctly at 400kHz with 1B.

But afterwards, that code referenced above is the last thing that is called before entering normal operation. So I assume that the 1B mode is forced in fact. Or at least I can't find anything that would suggest otherwise.

Maybe I should call the configuration function again myself.

Maybe this is just a work in progress and I need to do this by myself.

Thanks.