STM32
直播中

话多显蠢

10年用户 893经验值
擅长:479461
私信 关注
[问答]

STM32驱动eMMC读写数据的实现方法

STM32驱动eMMC读写数据的实现方法

回帖(1)

李月如

2021-12-15 10:59:57

参照 JEDEC eMMC标准:JESD84-B51 (Revision of JESD84-B50.1, July 2014)
驱动芯片采用stm32h7xx芯片。通过官方HAL库中stm32h7xx_hal_mmc.h文件驱动,采用8bit数据传输模式,与SD卡驱动类似。实测写入速度6-10MB/s左右。


初始化代码清单:


HAL_StatusTypeDef SDMMC1_MMC_Init(void)
{
  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 = 1;
  if (HAL_MMC_Init(&hmmc1) != HAL_OK)
  {
      Error_Handler();
  }
  return HAL_OK;
}


底层驱动代码清单:


void HAL_MMC_MspInit(MMC_HandleTypeDef* hmmc)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hmmc->Instance==SDMMC1)
  {
  /* USER CODE BEGIN SDMMC1_MspInit 0 */
    /* Peripheral 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
           PB8     ------> SDMMC1_D4
           PB9     ------> SDMMC1_D5
           PC6     ------> SDMMC1_D6
           PC7     ------> SDMMC1_D7
           PC12    ------> SDMMC1_CK
           PD2     ------> SDMMC1_CMD
    */
    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_8
                          |GPIO_PIN_9|GPIO_PIN_6|GPIO_PIN_7;
    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_8|GPIO_PIN_9;
    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(GPIOB, &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);
   
   HAL_NVIC_SetPriority(SDMMC1_IRQn,1,1);  //配置SDMMC1中断
   HAL_NVIC_EnableIRQ(SDMMC1_IRQn);        //使能SDMMC1中断
   HAL_NVIC_SetPriority(SysTick_IRQn, 0x0E ,0);
  }
}


在DMA模式下,从MMC卡的指定地址读取数据:


/**
  * @brief  在DMA模式下,从MMC卡的指定地址读取数据
  * @param  pData:指向将包含要传输的数据的缓冲区的指针
  * @param  ReadAddr:要读取数据的地址
  * @param  NumOfBlocks:要读取的MMC块数量
  * @retval eMMC状态
  */
uint8_t BSP_MMC_ReadBlocks_DMA(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
{
   HAL_StatusTypeDef Status =  HAL_OK;

   if(HAL_MMC_ReadBlocks_DMA(&hmmc1, pData, ReadAddr, NumOfBlocks) != HAL_OK)
   {
      Status = HAL_ERROR;
   }
   return Status;
}


在DMA模式下,向MMC卡的指定地址写入数据:


/**
  * @brief  在DMA模式下,向MMC卡的指定地址写入数据
  * @param  pData:指向将包含要传输的数据的缓冲区的指针
  * @param  WriteAddr:要写入数据的地址
  * @param  NumOfBlocks:要写的MMC块的数量
  * @retval MMC状态
  */
uint8_t BSP_MMC_WriteBlocks_DMA(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
{
  HAL_StatusTypeDef Status =  HAL_OK;
  
  /* Write block(s) in DMA transfer mode */
  if (HAL_MMC_WriteBlocks_DMA(&hmmc1, pData, WriteAddr, NumOfBlocks) != HAL_OK)
  {
    Status = HAL_ERROR;
  }
  return Status;
}


擦除eMMC卡数据:


/**
  * @brief  擦除eMMC卡数据
  * @param  无
  * @retval 无
  */
void MMC_EraseTest(void)
{
   HAL_StatusTypeDef Status = HAL_OK;
   HAL_StatusTypeDef EraseStatus = HAL_OK;
   if (Status == HAL_OK)
   {
      Status = HAL_MMC_Erase(&hmmc1, 0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));
      //等待擦除完成
      if(Wait_SDCARD_Ready() != HAL_OK)
      {
         EraseStatus = HAL_ERROR;
      }
   }
   if(EraseStatus != HAL_OK)
   {   
      Error_Handler();
   }
}


eMMC卡等待擦除完成函数:


/**
  * @brief  eMMC卡等待擦除完成函数
  * @param  无
  * @retval HAL_OK:擦除成功;HAL_ERROR:擦除失败
  */
static HAL_StatusTypeDef Wait_SDCARD_Ready(void)
{
   uint32_t loop = MMC_TIMEOUT;
   
   /* Wait for the Erasing process is completed */
   /* Verify that SD card is ready to use after the Erase */
   while(loop > 0)
   {
      loop--;
      if(HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)
      {
         return HAL_OK;
      }
   }
   return HAL_ERROR;
}


最近移植的eMMC卡的驱动程序,分享出来希望对各位开发者有所帮助。还移植了FATFS文件系统到eMMC驱动程序中,之后整理好再分享。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分