STM32驱动eMMC读写数据

本文介绍如何使用STM32H7xx驱动eMMC进行读写操作,遵循JESD84-B51标准,利用HAL库中的stm32h7xx_hal_mmc.h文件,实现8bit数据传输。实测写入速度为6-10MB/s。内容包括初始化、底层驱动代码、DMA模式下的读写及擦除操作。

STM32驱动eMMC读写数据

参照 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驱动程序中,之后整理好再分享。

评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值