[HAL][LL][SDMMC] Fix various bugs identified in MMC driver
- Take in account the voltage range in the CMD1 command.
- Add new LL function to have correct response for MMC driver.
- Update the driver to have all fields correctly initialized.
- Add a internal to manage the power class and call it before to update speed of bus width.
- Add new API to get the value of the Extended CSD register and populate the ExtCSD field of the MMC handle.
diff --git a/Inc/stm32f2xx_hal_mmc.h b/Inc/stm32f2xx_hal_mmc.h
index 111bc18..49d34dc 100644
--- a/Inc/stm32f2xx_hal_mmc.h
+++ b/Inc/stm32f2xx_hal_mmc.h
@@ -145,6 +145,8 @@
   
   uint32_t                     CID[4U];          /*!< MMC card identification number table */
   
+  uint32_t                     Ext_CSD[128];
+
 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
   void (* TxCpltCallback)                 (struct __MMC_HandleTypeDef *hmmc);
   void (* RxCpltCallback)                 (struct __MMC_HandleTypeDef *hmmc);
@@ -334,10 +336,12 @@
 /** 
   * @brief 
   */
-#define MMC_HIGH_VOLTAGE_RANGE         0x80FF8000U  /*!< VALUE OF ARGUMENT            */
-#define MMC_DUAL_VOLTAGE_RANGE         0x80FF8080U  /*!< VALUE OF ARGUMENT            */
-#define eMMC_HIGH_VOLTAGE_RANGE        0xC0FF8000U  /*!< for eMMC > 2Gb sector mode   */
-#define eMMC_DUAL_VOLTAGE_RANGE        0xC0FF8080U  /*!< for eMMC > 2Gb sector mode   */
+#define MMC_HIGH_VOLTAGE_RANGE         0x80FF8000U  /*!< High voltage in byte mode    */
+#define MMC_DUAL_VOLTAGE_RANGE         0x80FF8080U  /*!< Dual voltage in byte mode    */
+#define MMC_LOW_VOLTAGE_RANGE          0x80000080U  /*!< Low voltage in byte mode     */
+#define EMMC_HIGH_VOLTAGE_RANGE        0xC0FF8000U  /*!< High voltage in sector mode  */
+#define EMMC_DUAL_VOLTAGE_RANGE        0xC0FF8080U  /*!< Dual voltage in sector mode  */
+#define EMMC_LOW_VOLTAGE_RANGE         0xC0000080U  /*!< Low voltage in sector mode   */
 #define MMC_INVALID_VOLTAGE_RANGE      0x0001FF01U 
 /**
   * @}
@@ -636,6 +640,7 @@
 HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID);
 HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD);
 HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo);
+HAL_StatusTypeDef HAL_MMC_GetCardExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pExtCSD, uint32_t Timeout);
 /**
   * @}
   */
@@ -649,7 +654,7 @@
   * @}
   */
 
-/** @defgroup MMC_Exported_Functions_Group6 Perioheral Abort management
+/** @defgroup MMC_Exported_Functions_Group6 Peripheral Abort management
   * @{
   */
 HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc);
diff --git a/Inc/stm32f2xx_ll_sdmmc.h b/Inc/stm32f2xx_ll_sdmmc.h
index 625eef7..387d810 100644
--- a/Inc/stm32f2xx_ll_sdmmc.h
+++ b/Inc/stm32f2xx_ll_sdmmc.h
@@ -1059,8 +1059,14 @@
 
 /* SDMMC Cards mode management functions */
 HAL_StatusTypeDef SDIO_SetSDMMCReadWaitMode(SDIO_TypeDef *SDIOx, uint32_t SDIO_ReadWaitMode);
+/**
+  * @}
+  */
 
 /* SDMMC Commands management functions */
+/** @addtogroup HAL_SDMMC_LL_Group4
+  * @{
+  */
 uint32_t SDMMC_CmdBlockLength(SDIO_TypeDef *SDIOx, uint32_t BlockSize);
 uint32_t SDMMC_CmdReadSingleBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd);
 uint32_t SDMMC_CmdReadMultiBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd);
@@ -1081,13 +1087,26 @@
 uint32_t SDMMC_CmdSendSCR(SDIO_TypeDef *SDIOx);
 uint32_t SDMMC_CmdSendCID(SDIO_TypeDef *SDIOx);
 uint32_t SDMMC_CmdSendCSD(SDIO_TypeDef *SDIOx, uint32_t Argument);
-uint32_t SDMMC_CmdSendEXTCSD(SDIO_TypeDef *SDIOx, uint32_t Argument);
 uint32_t SDMMC_CmdSetRelAdd(SDIO_TypeDef *SDIOx, uint16_t *pRCA);
+uint32_t SDMMC_CmdSetRelAddMmc(SDIO_TypeDef *SDIOx, uint16_t RCA);
 uint32_t SDMMC_CmdSendStatus(SDIO_TypeDef *SDIOx, uint32_t Argument);
 uint32_t SDMMC_CmdStatusRegister(SDIO_TypeDef *SDIOx);
 uint32_t SDMMC_CmdOpCondition(SDIO_TypeDef *SDIOx, uint32_t Argument);
 uint32_t SDMMC_CmdSwitch(SDIO_TypeDef *SDIOx, uint32_t Argument);
+uint32_t SDMMC_CmdSendEXTCSD(SDIO_TypeDef *SDIOx, uint32_t Argument);
+/**
+  * @}
+  */
 
+/* SDMMC Responses management functions *****************************************/
+/** @addtogroup HAL_SDMMC_LL_Group5
+  * @{
+  */
+uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout);
+uint32_t SDMMC_GetCmdResp2(SDIO_TypeDef *SDIOx);
+uint32_t SDMMC_GetCmdResp3(SDIO_TypeDef *SDIOx);
+uint32_t SDMMC_GetCmdResp6(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint16_t *pRCA);
+uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx);
 /**
   * @}
   */
diff --git a/Src/stm32f2xx_hal_mmc.c b/Src/stm32f2xx_hal_mmc.c
index 8a91706..987fc6e 100644
--- a/Src/stm32f2xx_hal_mmc.c
+++ b/Src/stm32f2xx_hal_mmc.c
@@ -272,7 +272,30 @@
 /** @addtogroup MMC_Private_Defines
   * @{
   */
+#if defined (VDD_VALUE) && (VDD_VALUE <= 1950U)
+#define MMC_VOLTAGE_RANGE               EMMC_LOW_VOLTAGE_RANGE
 
+#define MMC_EXT_CSD_PWR_CL_26_INDEX     201
+#define MMC_EXT_CSD_PWR_CL_52_INDEX     200
+#define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 238
+
+#define MMC_EXT_CSD_PWR_CL_26_POS       8
+#define MMC_EXT_CSD_PWR_CL_52_POS       0
+#define MMC_EXT_CSD_PWR_CL_DDR_52_POS   16
+#else
+#define MMC_VOLTAGE_RANGE               EMMC_HIGH_VOLTAGE_RANGE
+
+#define MMC_EXT_CSD_PWR_CL_26_INDEX     203
+#define MMC_EXT_CSD_PWR_CL_52_INDEX     202
+#define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 239
+
+#define MMC_EXT_CSD_PWR_CL_26_POS       24
+#define MMC_EXT_CSD_PWR_CL_52_POS       16
+#define MMC_EXT_CSD_PWR_CL_DDR_52_POS   24
+#endif
+
+/* Frequencies used in the driver for clock divider calculation */
+#define MMC_INIT_FREQ                   400000U   /* Initalization phase : 400 kHz max */
 /**
   * @}
   */
@@ -296,6 +319,7 @@
 static void     MMC_DMAError(DMA_HandleTypeDef *hdma);
 static void     MMC_DMATxAbort(DMA_HandleTypeDef *hdma);
 static void     MMC_DMARxAbort(DMA_HandleTypeDef *hdma);
+static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide);
 /**
   * @}
   */
@@ -375,7 +399,7 @@
   }
 
   /* Initialize the error code */
-  hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
+  hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
 
   /* Initialize the MMC operation */
   hmmc->Context = MMC_CONTEXT_NONE;
@@ -383,6 +407,15 @@
   /* Initialize the MMC state */
   hmmc->State = HAL_MMC_STATE_READY;
 
+  /* Configure bus width */
+  if (hmmc->Init.BusWide != SDIO_BUS_WIDE_1B)
+  {
+    if (HAL_MMC_ConfigWideBusOperation(hmmc, hmmc->Init.BusWide) != HAL_OK)
+    {
+      return HAL_ERROR;
+    }
+  }
+
   return HAL_OK;
 }
 
@@ -1135,7 +1168,7 @@
 
   if(hmmc->State == HAL_MMC_STATE_READY)
   {
-    hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
+    hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
 
     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
     {
@@ -2080,6 +2113,122 @@
 }
 
 /**
+  * @brief  Returns information the information of the card which are stored on
+  *         the Extended CSD register.
+  * @param  hmmc Pointer to MMC handle
+  * @param  pExtCSD Pointer to a memory area (512 bytes) that contains all 
+  *         Extended CSD register parameters
+  * @param  Timeout Specify timeout value
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_MMC_GetCardExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pExtCSD, uint32_t Timeout)
+{
+  SDIO_DataInitTypeDef config;
+  uint32_t errorstate;
+  uint32_t tickstart = HAL_GetTick();
+  uint32_t count;
+  uint32_t *tmp_buf;
+
+  if(NULL == pExtCSD)
+  {
+    hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
+    return HAL_ERROR;
+  }
+
+  if(hmmc->State == HAL_MMC_STATE_READY)
+  {
+    hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
+
+    hmmc->State = HAL_MMC_STATE_BUSY;
+
+    /* Initialize data control register */
+    hmmc->Instance->DCTRL = 0;
+
+    /* Initiaize the destination pointer */
+    tmp_buf = pExtCSD;
+
+    /* Configure the MMC DPSM (Data Path State Machine) */
+    config.DataTimeOut   = SDMMC_DATATIMEOUT;
+    config.DataLength    = 512;
+    config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
+    config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
+    config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
+    config.DPSM          = SDIO_DPSM_ENABLE;
+    (void)SDIO_ConfigData(hmmc->Instance, &config);
+
+    /* Send ExtCSD Read command to Card */
+    errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
+    if(errorstate != HAL_MMC_ERROR_NONE)
+    {
+      /* Clear all the static flags */
+      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
+      hmmc->ErrorCode |= errorstate;
+      hmmc->State = HAL_MMC_STATE_READY;
+      return HAL_ERROR;
+    }
+
+    /* Poll on SDMMC flags */
+    while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND))
+    {
+      if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF))
+      {
+        /* Read data from SDMMC Rx FIFO */
+        for(count = 0U; count < 8U; count++)
+        {
+          *tmp_buf = SDIO_ReadFIFO(hmmc->Instance);
+          tmp_buf++;
+        }
+      }
+
+      if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
+      {
+        /* Clear all the static flags */
+        __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
+        hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
+        hmmc->State= HAL_MMC_STATE_READY;
+        return HAL_TIMEOUT;
+      }
+    }
+
+    /* Get error state */
+    if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
+    {
+      /* Clear all the static flags */
+      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
+      hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
+      hmmc->State = HAL_MMC_STATE_READY;
+      return HAL_ERROR;
+    }
+    else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
+    {
+      /* Clear all the static flags */
+      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
+      hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
+      hmmc->State = HAL_MMC_STATE_READY;
+      return HAL_ERROR;
+    }
+    else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR))
+    {
+      /* Clear all the static flags */
+      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
+      hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
+      hmmc->State = HAL_MMC_STATE_READY;
+      return HAL_ERROR;
+    }
+    else
+    {
+      /* Nothing to do */
+    }
+
+    /* Clear all the static flags */
+    __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
+    hmmc->State = HAL_MMC_STATE_READY;
+  }
+
+  return HAL_OK;
+}
+
+/**
   * @brief  Enables wide bus operation for the requested card if supported by
   *         card.
   * @param  hmmc: Pointer to MMC handle
@@ -2092,10 +2241,10 @@
   */
 HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
 {
-  __IO uint32_t count = 0U;
+  uint32_t count;
   SDIO_InitTypeDef Init;
   uint32_t errorstate;
-  uint32_t response = 0U, busy = 0U;
+  uint32_t response = 0U;
 
   /* Check the parameters */
   assert_param(IS_SDIO_BUS_WIDE(WideMode));
@@ -2103,116 +2252,84 @@
   /* Change State */
   hmmc->State = HAL_MMC_STATE_BUSY;
 
-  /* Update Clock for Bus mode update */
-  Init.ClockEdge           = SDIO_CLOCK_EDGE_RISING;
-  Init.ClockBypass         = SDIO_CLOCK_BYPASS_DISABLE;
-  Init.ClockPowerSave      = SDIO_CLOCK_POWER_SAVE_DISABLE;
-  Init.BusWide             = WideMode;
-  Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
-  Init.ClockDiv            = SDIO_INIT_CLK_DIV;
-  /* Initialize SDIO*/
-  (void)SDIO_Init(hmmc->Instance, Init); 
+  errorstate = MMC_PwrClassUpdate(hmmc, WideMode);
 
-  if(WideMode == SDIO_BUS_WIDE_8B)
+  if(errorstate == HAL_MMC_ERROR_NONE)
   {
-    errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
-    if(errorstate != HAL_MMC_ERROR_NONE)
+    if(WideMode == SDIO_BUS_WIDE_8B)
     {
-      hmmc->ErrorCode |= errorstate;
+      errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
     }
-  }
-  else if(WideMode == SDIO_BUS_WIDE_4B)
-  {
-    errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
-    if(errorstate != HAL_MMC_ERROR_NONE)
+    else if(WideMode == SDIO_BUS_WIDE_4B)
     {
-      hmmc->ErrorCode |= errorstate;
+      errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
     }
-  }
-  else if(WideMode == SDIO_BUS_WIDE_1B)
-  {
-    errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
-    if(errorstate != HAL_MMC_ERROR_NONE)
+    else if(WideMode == SDIO_BUS_WIDE_1B)
     {
-      hmmc->ErrorCode |= errorstate;
+      errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
     }
-  }
-  else
-  {
-    /* WideMode is not a valid argument*/
-    hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
-  }
-
-  /* Check for switch error and violation of the trial number of sending CMD 13 */
-  while(busy == 0U)
-  {
-    if(count == SDMMC_MAX_TRIAL)
+    else
     {
-      hmmc->State = HAL_MMC_STATE_READY;
-      hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
-      return HAL_ERROR;
-    }
-    count++;
-
-    /* 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;
+      /* WideMode is not a valid argument*/
+      errorstate = HAL_MMC_ERROR_PARAM;
     }
 
-    /* Get command response */
-    response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
-
-    /* Get operating voltage*/
-    busy = (((response >> 7U) == 1U) ? 0U : 1U);
-  }
-
-  /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
-  count = SDMMC_DATATIMEOUT;
-  while((response & 0x00000100U) == 0U)
-  {
-    if(count == 0U)
+    /* Check for switch error and violation of the trial number of sending CMD 13 */
+    if(errorstate == HAL_MMC_ERROR_NONE)
     {
-      hmmc->State = HAL_MMC_STATE_READY;
-      hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
-      return HAL_ERROR;
+      /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
+      count = SDMMC_MAX_TRIAL;
+      do
+      {
+        errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
+        if(errorstate != HAL_MMC_ERROR_NONE)
+        {
+          break;
+        }
+        
+        /* Get command response */
+        response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
+        count--;
+      }while(((response & 0x100U) == 0U) && (count != 0U));
+
+      /* Check the status after the switch command execution */
+      if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
+      {
+        /* Check the bit SWITCH_ERROR of the device status */
+        if ((response & 0x80U) != 0U)
+        {
+          errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
+        }
+        else
+        {
+          /* Configure the SDIO peripheral */
+          Init = hmmc->Init;
+          Init.BusWide = WideMode;
+          (void)SDIO_Init(hmmc->Instance, Init);
+        }
+      }
+      else if (count == 0U)
+      {
+        errorstate = SDMMC_ERROR_TIMEOUT;
+      }
+      else
+      {
+        /* Nothing to do */
+      }
     }
-    count--;
-
-    /* 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;
-    }
-
-    /* Get command response */
-    response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
-  }
-
-  if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
-  {
-    /* Clear all the static flags */
-    __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
-    hmmc->State = HAL_MMC_STATE_READY;
-    return HAL_ERROR;
-  }
-  else
-  {
-    /* Configure the SDIO peripheral */
-    Init.ClockEdge           = hmmc->Init.ClockEdge;
-    Init.ClockBypass         = hmmc->Init.ClockBypass;
-    Init.ClockPowerSave      = hmmc->Init.ClockPowerSave;
-    Init.BusWide             = WideMode;
-    Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
-    Init.ClockDiv            = hmmc->Init.ClockDiv;
-    (void)SDIO_Init(hmmc->Instance, Init);
   }
 
   /* Change State */
   hmmc->State = HAL_MMC_STATE_READY;
 
+  if(errorstate != HAL_MMC_ERROR_NONE)
+  {
+    /* Clear all the static flags */
+    __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
+    hmmc->ErrorCode |= errorstate;
+    return HAL_ERROR;
+  }
+
   return HAL_OK;
 }
 
@@ -2573,7 +2690,8 @@
 {
   HAL_MMC_CardCSDTypeDef CSD;
   uint32_t errorstate;
-  uint16_t mmc_rca = 1U;
+  uint16_t mmc_rca = 2U;
+  MMC_InitTypeDef Init;
 
   /* Check the power State */
   if(SDIO_GetPowerState(hmmc->Instance) == 0U)
@@ -2597,9 +2715,9 @@
     hmmc->CID[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4);
   }
 
-  /* Send CMD3 SET_REL_ADDR with argument 0 */
+  /* Send CMD3 SET_REL_ADDR with RCA = 2 (should be greater than 1) */
   /* MMC Card publishes its RCA. */
-  errorstate = SDMMC_CmdSetRelAdd(hmmc->Instance, &mmc_rca);
+  errorstate = SDMMC_CmdSetRelAddMmc(hmmc->Instance, mmc_rca);
   if(errorstate != HAL_MMC_ERROR_NONE)
   {
     return errorstate;
@@ -2626,12 +2744,6 @@
   /* Get the Card Class */
   hmmc->MmcCard.Class = (SDIO_GetResponse(hmmc->Instance, SDIO_RESP2) >> 20U);
 
-  /* Get CSD parameters */
-  if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
-  {
-    return hmmc->ErrorCode;
-  }
-
   /* Select the Card */
   errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
   if(errorstate != HAL_MMC_ERROR_NONE)
@@ -2639,8 +2751,36 @@
     return errorstate;
   }
 
-  /* Configure SDIO peripheral interface */
-  (void)SDIO_Init(hmmc->Instance, hmmc->Init);
+  /* 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;
+  }
+  
+  /* Get Extended CSD parameters */
+  if (HAL_MMC_GetCardExtCSD(hmmc, hmmc->Ext_CSD, SDMMC_DATATIMEOUT) != 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 SDIO peripheral */
+  Init = hmmc->Init;
+  Init.BusWide = SDIO_BUS_WIDE_1B;
+  (void)SDIO_Init(hmmc->Instance, Init);
 
   /* All cards are initialized */
   return HAL_MMC_ERROR_NONE;
@@ -2673,8 +2813,8 @@
       return HAL_MMC_ERROR_INVALID_VOLTRANGE;
     }
 
-    /* SEND CMD1 APP_CMD with MMC_HIGH_VOLTAGE_RANGE(0xC0FF8000) as argument */
-    errorstate = SDMMC_CmdOpCondition(hmmc->Instance, eMMC_HIGH_VOLTAGE_RANGE);
+    /* SEND CMD1 APP_CMD with voltage range as argument */
+    errorstate = SDMMC_CmdOpCondition(hmmc->Instance, MMC_VOLTAGE_RANGE);
     if(errorstate != HAL_MMC_ERROR_NONE)
     {
       return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
@@ -2906,6 +3046,93 @@
 }
 
 /**
+  * @brief  Update the power class of the device.
+  * @param  hmmc MMC handle
+  * @param  Wide Wide of MMC bus
+  * @param  Speed Speed of the MMC bus
+  * @retval MMC Card error state
+  */
+static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide)
+{
+  uint32_t count;
+  uint32_t response = 0U;
+  uint32_t errorstate = HAL_MMC_ERROR_NONE;
+  uint32_t power_class, supported_pwr_class;
+
+  if((Wide == SDIO_BUS_WIDE_8B) || (Wide == SDIO_BUS_WIDE_4B))
+  {
+    power_class = 0U; /* Default value after power-on or software reset */
+
+    /* Read the PowerClass field of the Extended CSD register */
+    if(MMC_ReadExtCSD(hmmc, &power_class, 187, SDMMC_DATATIMEOUT) != HAL_OK) /* Field POWER_CLASS [187] */
+    {
+      errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
+    }
+    else
+    {
+      power_class = ((power_class >> 24U) & 0x000000FFU);
+    }
+
+    /* Get the supported PowerClass field of the Extended CSD register */
+    /* Field PWR_CL_26_xxx [201 or 203] */
+    supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_26_INDEX/4)] >> MMC_EXT_CSD_PWR_CL_26_POS) & 0x000000FFU);
+
+    if(errorstate == HAL_MMC_ERROR_NONE)
+    {
+      if(Wide == SDIO_BUS_WIDE_8B)
+      {
+        /* Bit [7:4] : power class for 8-bits bus configuration - Bit [3:0] : power class for 4-bits bus configuration */
+        supported_pwr_class = (supported_pwr_class >> 4U);
+      }
+
+      if ((power_class & 0x0FU) != (supported_pwr_class & 0x0FU))
+      {
+        /* Need to change current power class */
+        errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03BB0000U | ((supported_pwr_class & 0x0FU) << 8U)));
+
+        if(errorstate == HAL_MMC_ERROR_NONE)
+        {
+          /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
+          count = SDMMC_MAX_TRIAL;
+          do
+          {
+            errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
+            if(errorstate != HAL_MMC_ERROR_NONE)
+            {
+              break;
+            }
+
+            /* Get command response */
+            response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
+            count--;
+          }while(((response & 0x100U) == 0U) && (count != 0U));
+
+          /* Check the status after the switch command execution */
+          if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
+          {
+            /* Check the bit SWITCH_ERROR of the device status */
+            if ((response & 0x80U) != 0U)
+            {
+              errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
+            }
+          }
+          else if (count == 0U)
+          {
+            errorstate = SDMMC_ERROR_TIMEOUT;
+          }
+          else
+          {
+            /* Nothing to do */
+          }
+        }
+      }
+    }
+  }
+
+  return errorstate;
+}
+
+/**
   * @}
   */
 
diff --git a/Src/stm32f2xx_ll_sdmmc.c b/Src/stm32f2xx_ll_sdmmc.c
index 2dd5440..a50dea9 100644
--- a/Src/stm32f2xx_ll_sdmmc.c
+++ b/Src/stm32f2xx_ll_sdmmc.c
@@ -177,11 +177,6 @@
 /* Private variables ---------------------------------------------------------*/
 /* Private function prototypes -----------------------------------------------*/
 static uint32_t SDMMC_GetCmdError(SDIO_TypeDef *SDIOx);
-static uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout);
-static uint32_t SDMMC_GetCmdResp2(SDIO_TypeDef *SDIOx);
-static uint32_t SDMMC_GetCmdResp3(SDIO_TypeDef *SDIOx);
-static uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx);
-static uint32_t SDMMC_GetCmdResp6(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint16_t *pRCA);
 
 /* Exported functions --------------------------------------------------------*/
 
@@ -1027,6 +1022,31 @@
 }
 
 /**
+  * @brief  Send the Set Relative Address command to MMC card (not SD card).
+  * @param  SDIOx Pointer to SDIO register base
+  * @param  RCA Card RCA
+  * @retval HAL status
+  */
+uint32_t SDMMC_CmdSetRelAddMmc(SDIO_TypeDef *SDIOx, uint16_t RCA)
+{
+  SDIO_CmdInitTypeDef  sdmmc_cmdinit;
+  uint32_t errorstate;
+
+  /* Send CMD3 SD_CMD_SET_REL_ADDR */
+  sdmmc_cmdinit.Argument         = ((uint32_t)RCA << 16U);
+  sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_REL_ADDR;
+  sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
+  sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
+  sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
+  (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
+
+  /* Check for error conditions */
+  errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SET_REL_ADDR, SDIO_CMDTIMEOUT);
+
+  return errorstate;
+}
+
+/**
   * @brief  Send the Status command and check the response.
   * @param  SDIOx: Pointer to SDIO register base 
   * @param  Argument: Command Argument
@@ -1125,47 +1145,54 @@
 }
 
 /**
-  * @}
+  * @brief  Send the Send EXT_CSD command and check the response.
+  * @param  SDIOx Pointer to SDMMC register base
+  * @param  Argument Command Argument
+  * @retval HAL status
   */
-
-/* Private function ----------------------------------------------------------*/  
-/** @addtogroup SD_Private_Functions
-  * @{
-  */
-    
-/**
-  * @brief  Checks for error conditions for CMD0.
-  * @param  hsd: SD handle
-  * @retval SD Card error state
-  */
-static uint32_t SDMMC_GetCmdError(SDIO_TypeDef *SDIOx)
+uint32_t SDMMC_CmdSendEXTCSD(SDIO_TypeDef *SDIOx, uint32_t Argument)
 {
-  /* 8 is the number of required instructions cycles for the below loop statement.
-  The SDIO_CMDTIMEOUT is expressed in ms */
-  uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
-  
-  do
-  {
-    if (count-- == 0U)
-    {
-      return SDMMC_ERROR_TIMEOUT;
-    }
-    
-  }while(!__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CMDSENT));
-  
-  /* Clear all the static flags */
-  __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
-  
-  return SDMMC_ERROR_NONE;
+  SDIO_CmdInitTypeDef  sdmmc_cmdinit;
+  uint32_t errorstate;
+
+  /* Send CMD9 SEND_CSD */
+  sdmmc_cmdinit.Argument         = Argument;
+  sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SEND_EXT_CSD;
+  sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
+  sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
+  sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
+  (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
+
+  /* Check for error conditions */
+  errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_HS_SEND_EXT_CSD,SDIO_CMDTIMEOUT);
+
+  return errorstate;
 }
 
 /**
+  * @}
+  */
+
+/** @defgroup HAL_SDMMC_LL_Group5 Responses management functions
+ *  @brief   Responses functions
+ *
+@verbatim
+ ===============================================================================
+                   ##### Responses management functions #####
+ ===============================================================================
+    [..]
+    This subsection provides a set of functions allowing to manage the needed responses.
+
+@endverbatim
+  * @{
+  */
+/**
   * @brief  Checks for error conditions for R1 response.
-  * @param  hsd: SD handle
+  * @param  SDIOx Pointer to SDMMC register base
   * @param  SD_CMD: The sent command index  
   * @retval SD Card error state
   */
-static uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout)
+uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout)
 {
   uint32_t response_r1;
   uint32_t sta_reg;
@@ -1297,10 +1324,10 @@
 
 /**
   * @brief  Checks for error conditions for R2 (CID or CSD) response.
-  * @param  hsd: SD handle
+  * @param  SDIOx Pointer to SDMMC register base
   * @retval SD Card error state
   */
-static uint32_t SDMMC_GetCmdResp2(SDIO_TypeDef *SDIOx)
+uint32_t SDMMC_GetCmdResp2(SDIO_TypeDef *SDIOx)
 {
   uint32_t sta_reg;
   /* 8 is the number of required instructions cycles for the below loop statement.
@@ -1341,10 +1368,10 @@
 
 /**
   * @brief  Checks for error conditions for R3 (OCR) response.
-  * @param  hsd: SD handle
+  * @param  SDIOx Pointer to SDMMC register base
   * @retval SD Card error state
   */
-static uint32_t SDMMC_GetCmdResp3(SDIO_TypeDef *SDIOx)
+uint32_t SDMMC_GetCmdResp3(SDIO_TypeDef *SDIOx)
 {
   uint32_t sta_reg;
   /* 8 is the number of required instructions cycles for the below loop statement.
@@ -1378,13 +1405,13 @@
 
 /**
   * @brief  Checks for error conditions for R6 (RCA) response.
-  * @param  hsd: SD handle
+  * @param  SDIOx Pointer to SDMMC register base
   * @param  SD_CMD: The sent command index
   * @param  pRCA: Pointer to the variable that will contain the SD card relative 
   *         address RCA   
   * @retval SD Card error state
   */
-static uint32_t SDMMC_GetCmdResp6(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint16_t *pRCA)
+uint32_t SDMMC_GetCmdResp6(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint16_t *pRCA)
 {
   uint32_t response_r1;
   uint32_t sta_reg;
@@ -1454,10 +1481,10 @@
 
 /**
   * @brief  Checks for error conditions for R7 response.
-  * @param  hsd: SD handle
+  * @param  SDIOx Pointer to SDMMC register base
   * @retval SD Card error state
   */
-static uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx)
+uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx)
 {
   uint32_t sta_reg;
   /* 8 is the number of required instructions cycles for the below loop statement.
@@ -1504,28 +1531,38 @@
 }
 
 /**
-  * @brief  Send the Send EXT_CSD command and check the response.
-  * @param  SDIOx: Pointer to SDMMC register base
-  * @param  Argument: Command Argument
-  * @retval HAL status
+  * @}
   */
-uint32_t SDMMC_CmdSendEXTCSD(SDIO_TypeDef *SDIOx, uint32_t Argument)
+
+/* Private function ----------------------------------------------------------*/  
+/** @addtogroup SD_Private_Functions
+  * @{
+  */
+    
+/**
+  * @brief  Checks for error conditions for CMD0.
+  * @param  SDIOx Pointer to SDMMC register base
+  * @retval SD Card error state
+  */
+static uint32_t SDMMC_GetCmdError(SDIO_TypeDef *SDIOx)
 {
-  SDIO_CmdInitTypeDef  sdmmc_cmdinit;
-  uint32_t errorstate;
-
-  /* Send CMD9 SEND_CSD */
-  sdmmc_cmdinit.Argument         = Argument;
-  sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SEND_EXT_CSD;
-  sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
-  sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
-  sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
-  (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
-
-  /* Check for error conditions */
-  errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_HS_SEND_EXT_CSD,SDIO_CMDTIMEOUT);
-
-  return errorstate;
+  /* 8 is the number of required instructions cycles for the below loop statement.
+  The SDIO_CMDTIMEOUT is expressed in ms */
+  uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
+  
+  do
+  {
+    if (count-- == 0U)
+    {
+      return SDMMC_ERROR_TIMEOUT;
+    }
+    
+  }while(!__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CMDSENT));
+  
+  /* Clear all the static flags */
+  __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
+  
+  return SDMMC_ERROR_NONE;
 }