Skip to main content
Jack3
Senior
May 12, 2020
Question

SDMMC fixed

  • May 12, 2020
  • 3 replies
  • 3177 views

I already reported this bug up at previous versions of the STM32H7 firmware.

Now I'm using

  • STM32CubeMX 5.6.1
  • STM32CubeIDE 1.3.1 (arm-none-eabi-gcc 7.3.1)
  • STM32Cube FW_H7 V1.7.0

For those who find SDMMC not working, there still is an obvious bug , the way the code is generated by STM32CubeMX. If we look at the below code:

void MX_SDMMC1_SD_Init(void)
{
 
 hsd1.Instance = SDMMC1;
 hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
 hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
 hsd1.Init.BusWide = SDMMC_BUS_WIDE_4B;
 hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
 hsd1.Init.ClockDiv = 2;
 hsd1.Init.TranceiverPresent = SDMMC_TRANSCEIVER_NOT_PRESENT;
 
}

We seem to be missing a few lines in there.

EDIT: DTK mentioned this, because the Init code was missing the initialization functions, I also changed the bits to 8 because of thinking of eMMC I also use. But this was for SD-cards, where I use 4-bit sofar, a slip of the pen. Now Clive just did show that 8-bit SD-Cards also exist, so it still would be valid. In my working code, I did correct fine though, and it works, because after generation I always add and change things and don't let STM32CubeMX modify it anymore. Because not everywhere always are comment lines where I need to change things.

This is just about wondering why the generated code is missing the init function after filling the structure. The ioc file is below, maybe there is an error in there.

Now I need to test if STM32CubeMX always leaves the init function out, both for SD and MMC.

So now I added SD and MMC parts.

SD:

void MX_SDMMC1_SD_Init(void)
{
 hsd1.Instance = SDMMC1;
 hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
 hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
 hsd1.Init.BusWide = SDMMC_BUS_WIDE_4B;
 hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
 hsd1.Init.ClockDiv = 2;
 hsd1.Init.TranceiverPresent = SDMMC_TRANSCEIVER_NOT_PRESENT;
 
 if (HAL_SD_Init(&hsd1) != HAL_OK)
 {
 Error_Handler();
 }
}

MMC:

void MX_SDMMC1_MMC_Init(void)
{
 hmmc1.Instance = SDMMC1;
 hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
 hmmc1.Init.ClockBypass = SDMMC_CLOCK_BYPASS_ENABLE;
 hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
 hmmc1.Init.BusWide = SDMMC_BUS_WIDE_8B;
 hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_ENABLE;
 hmmc1.Init.ClockDiv = 0;
 if (HAL_MMC_Init(&hmmc1) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }
}

I hope this helps somebody.

It brought his to ST attention, and it is still like this, maybe I do something wrong?

I'm mainly using HAL.

I'm also not sure why they removed __FILE__, __LINE__ from the Error_Handler. How would that benefit?

I hope the suggestions will finally make it o the ST developers in charge. But...

The complete sdmmc.c file, unmodified looks like:

/**
 ******************************************************************************
 * File Name : SDMMC.c
 * Description : This file provides code for the configuration
 * of the SDMMC instances.
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
 * All rights reserved.</center></h2>
 *
 * This software component is licensed by ST under Ultimate Liberty license
 * SLA0044, the "License"; You may not use this file except in compliance with
 * the License. You may obtain a copy of the License at:
 * www.st.com/SLA0044
 *
 ******************************************************************************
 */
 
/* Includes ------------------------------------------------------------------*/
#include "sdmmc.h"
 
/* USER CODE BEGIN 0 */
 
/* USER CODE END 0 */
 
SD_HandleTypeDef hsd1;
 
/* SDMMC1 init function */
 
void MX_SDMMC1_SD_Init(void)
{
 
 hsd1.Instance = SDMMC1;
 hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
 hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
 hsd1.Init.BusWide = SDMMC_BUS_WIDE_8B;
 hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
 hsd1.Init.ClockDiv = 2;
 hsd1.Init.TranceiverPresent = SDMMC_TRANSCEIVER_NOT_PRESENT;
 
}
 
void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle)
{
 
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 if(sdHandle->Instance==SDMMC1)
 {
 /* USER CODE BEGIN SDMMC1_MspInit 0 */
 
 /* USER CODE END SDMMC1_MspInit 0 */
 /* SDMMC1 clock enable */
 __HAL_RCC_SDMMC1_CLK_ENABLE();
 
 __HAL_RCC_GPIOC_CLK_ENABLE();
 __HAL_RCC_GPIOD_CLK_ENABLE();
 /**SDMMC1 GPIO Configuration 
 PC8 ------> SDMMC1_D0
 PC9 ------> SDMMC1_D1
 PC10 ------> SDMMC1_D2
 PC11 ------> SDMMC1_D3
 PC12 ------> SDMMC1_CK
 PD2 ------> SDMMC1_CMD 
 */
 GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 
 |GPIO_PIN_12;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = GPIO_PIN_2;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 
 /* SDMMC1 interrupt Init */
 HAL_NVIC_SetPriority(SDMMC1_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(SDMMC1_IRQn);
 /* USER CODE BEGIN SDMMC1_MspInit 1 */
 
 /* USER CODE END SDMMC1_MspInit 1 */
 }
}
 
void HAL_SD_MspDeInit(SD_HandleTypeDef* sdHandle)
{
 
 if(sdHandle->Instance==SDMMC1)
 {
 /* USER CODE BEGIN SDMMC1_MspDeInit 0 */
 
 /* USER CODE END SDMMC1_MspDeInit 0 */
 /* Peripheral clock disable */
 __HAL_RCC_SDMMC1_CLK_DISABLE();
 
 /**SDMMC1 GPIO Configuration 
 PC8 ------> SDMMC1_D0
 PC9 ------> SDMMC1_D1
 PC10 ------> SDMMC1_D2
 PC11 ------> SDMMC1_D3
 PC12 ------> SDMMC1_CK
 PD2 ------> SDMMC1_CMD 
 */
 HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 
 |GPIO_PIN_12);
 
 HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);
 
 /* SDMMC1 interrupt Deinit */
 HAL_NVIC_DisableIRQ(SDMMC1_IRQn);
 /* USER CODE BEGIN SDMMC1_MspDeInit 1 */
 
 /* USER CODE END SDMMC1_MspDeInit 1 */
 }
} 
 
/* USER CODE BEGIN 1 */
 
/* USER CODE END 1 */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

This topic has been closed for replies.

3 replies

TDK
Super User
May 13, 2020

There is no 8-bit mode for SD cards. Your code also doesn't have the user code block comments. Are you sure that was generated by CubeMX and not something that you modified?

I just generated a new STM32H743 project with the same versions you call out and could not reproduce. Both 8-bit MMC and 4-bit SD initialization code works fine.

/**
 * @brief SDMMC1 Initialization Function
 * @param None
 * @retval None
 */
static void MX_SDMMC1_SD_Init(void)
{
 
 /* USER CODE BEGIN SDMMC1_Init 0 */
 
 /* USER CODE END SDMMC1_Init 0 */
 
 /* USER CODE BEGIN SDMMC1_Init 1 */
 
 /* USER CODE END SDMMC1_Init 1 */
 hsd1.Instance = SDMMC1;
 hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
 hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
 hsd1.Init.BusWide = SDMMC_BUS_WIDE_4B;
 hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
 hsd1.Init.ClockDiv = 0;
 hsd1.Init.TranceiverPresent = SDMMC_TRANSCEIVER_NOT_PRESENT;
 if (HAL_SD_Init(&hsd1) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN SDMMC1_Init 2 */
 
 /* USER CODE END SDMMC1_Init 2 */
 
}

/**
 * @brief SDMMC1 Initialization Function
 * @param None
 * @retval None
 */
static void MX_SDMMC1_MMC_Init(void)
{
 
 /* USER CODE BEGIN SDMMC1_Init 0 */
 
 /* USER CODE END SDMMC1_Init 0 */
 
 /* USER CODE BEGIN SDMMC1_Init 1 */
 
 /* USER CODE END SDMMC1_Init 1 */
 hmmc1.Instance = SDMMC1;
 hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
 hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
 hmmc1.Init.BusWide = SDMMC_BUS_WIDE_8B;
 hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
 hmmc1.Init.ClockDiv = 0;
 hmmc1.Init.TranceiverPresent = SDMMC_TRANSCEIVER_NOT_PRESENT;
 if (HAL_MMC_Init(&hmmc1) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN SDMMC1_Init 2 */
 
 /* USER CODE END SDMMC1_Init 2 */
 
}

"If you feel a post has answered your question, please click ""Accept as Solution""."
Jack3
Jack3Author
Senior
May 20, 2020

Hi TDK, thanks for trying that. I confirm it is an inconsistent result.

  

I use the SDMMC peripheral in 8-bits mode with 8-bit eMMC memory cards (16GB) or in 4-bits mode with SD-Cards.

I noticed the incomplete init function in the generated files, with no warning.

This one was for SD.

Tesla DeLorean
Guru
May 20, 2020

eMMC 8-Bit and DDR on both H7 and L4+ platforms, works quite well, 64 GB and 128 GB, good for automotive temps and high vibration environments.

MMCPlus (MMC+) cards had an 8-bit flavour, have a couple, but the sockets are impossible to find now.

0693W000001cdWuQAI.jpg

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Jack3
Jack3Author
Senior
May 18, 2020

Yes, I think so. I checked: STM32CubeMX 5.6.1

sdmmc.c:

/**
 ******************************************************************************
 * File Name : SDMMC.c
 * Description : This file provides code for the configuration
 * of the SDMMC instances.
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
 * All rights reserved.</center></h2>
 *
 * This software component is licensed by ST under Ultimate Liberty license
 * SLA0044, the "License"; You may not use this file except in compliance with
 * the License. You may obtain a copy of the License at:
 * www.st.com/SLA0044
 *
 ******************************************************************************
 */
 
/* Includes ------------------------------------------------------------------*/
#include "sdmmc.h"
 
/* USER CODE BEGIN 0 */
 
/* USER CODE END 0 */
 
SD_HandleTypeDef hsd1;
 
/* SDMMC1 init function */
 
void MX_SDMMC1_SD_Init(void)
{
 
 hsd1.Instance = SDMMC1;
 hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
 hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
 hsd1.Init.BusWide = SDMMC_BUS_WIDE_8B;
 hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
 hsd1.Init.ClockDiv = 2;
 hsd1.Init.TranceiverPresent = SDMMC_TRANSCEIVER_NOT_PRESENT;
 
}
 
void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle)
{
 
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 if(sdHandle->Instance==SDMMC1)
 {
 /* USER CODE BEGIN SDMMC1_MspInit 0 */
 
 /* USER CODE END SDMMC1_MspInit 0 */
 /* SDMMC1 clock enable */
 __HAL_RCC_SDMMC1_CLK_ENABLE();
 
 __HAL_RCC_GPIOC_CLK_ENABLE();
 __HAL_RCC_GPIOD_CLK_ENABLE();
 /**SDMMC1 GPIO Configuration 
 PC8 ------> SDMMC1_D0
 PC9 ------> SDMMC1_D1
 PC10 ------> SDMMC1_D2
 PC11 ------> SDMMC1_D3
 PC12 ------> SDMMC1_CK
 PD2 ------> SDMMC1_CMD 
 */
 GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 
 |GPIO_PIN_12;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = GPIO_PIN_2;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 
 /* SDMMC1 interrupt Init */
 HAL_NVIC_SetPriority(SDMMC1_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(SDMMC1_IRQn);
 /* USER CODE BEGIN SDMMC1_MspInit 1 */
 
 /* USER CODE END SDMMC1_MspInit 1 */
 }
}
 
void HAL_SD_MspDeInit(SD_HandleTypeDef* sdHandle)
{
 
 if(sdHandle->Instance==SDMMC1)
 {
 /* USER CODE BEGIN SDMMC1_MspDeInit 0 */
 
 /* USER CODE END SDMMC1_MspDeInit 0 */
 /* Peripheral clock disable */
 __HAL_RCC_SDMMC1_CLK_DISABLE();
 
 /**SDMMC1 GPIO Configuration 
 PC8 ------> SDMMC1_D0
 PC9 ------> SDMMC1_D1
 PC10 ------> SDMMC1_D2
 PC11 ------> SDMMC1_D3
 PC12 ------> SDMMC1_CK
 PD2 ------> SDMMC1_CMD 
 */
 HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 
 |GPIO_PIN_12);
 
 HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);
 
 /* SDMMC1 interrupt Deinit */
 HAL_NVIC_DisableIRQ(SDMMC1_IRQn);
 /* USER CODE BEGIN SDMMC1_MspDeInit 1 */
 
 /* USER CODE END SDMMC1_MspDeInit 1 */
 }
} 
 
/* USER CODE BEGIN 1 */
 
/* USER CODE END 1 */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

I did not modify this.

Please find the ioc file below.

Jack3
Jack3Author
Senior
May 18, 2020