当前位置:   article > 正文

STM32使用HAL库驱动EMMC挂载FATFS文件系统_stm32 emmc

stm32 emmc


工程需要使用EMMC挂载FATFS文件系统,苦苦寻找皆为SD卡挂载FATFS,虽原理一样还是写了这么一篇博客,希望对新手可以有些帮助!!!

STM32驱动EMMC

使用STM32CubeMX配置SDIO

  1. 选择SDIO选项
    在这里插入图片描述
  2. 配置DMA
    在这里插入图片描述
  3. 选择中断优先级
    在这里插入图片描述

编写EMMC驱动

等待EMMC就绪

uint8_t WaitEMMCReady(void)
{
	uint8_t count = EMMC_TIMEOUT;
	while(count--)
	{
		if(HAL_MMC_GetCardState(&hmmc)== HAL_MMC_CARD_TRANSFER)
		{
			return HAL_OK;
		}
		HAL_Delay(1);
	}
	return HAL_ERROR;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

EMMC读取n(n>=1)块

HAL_StatusTypeDef EMMC_ReadBlock_DMA(uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
{
	HAL_StatusTypeDef Status =  HAL_OK;
	if(WaitEMMCReady() != HAL_OK)
	{
		Status = HAL_BUSY;
	}
   HAL_DMA_DeInit(&hdma_sdio);
   hdma_sdio.Instance = DMA2_Channel4;
   hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;
   hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
   hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
   hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
   hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
   hdma_sdio.Init.Mode = DMA_NORMAL;
   hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
   if(HAL_DMA_Init(&hdma_sdio) != HAL_OK)
   {
       Error_Handler();
   }

  __HAL_LINKDMA(&hmmc, hdmarx, hdma_sdio);
	if(HAL_MMC_ReadBlocks_DMA(&hmmc, pData, BlockAdd, NumberOfBlocks) != HAL_OK)
  {
     Status = HAL_ERROR;
  } 
   return Status; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

EMMC写入n(n>=1)块

HAL_StatusTypeDef EMMC_WriteBlock_DMA(uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
{
	HAL_StatusTypeDef Status =  HAL_OK;
  if(WaitEMMCReady() != HAL_OK)
	{
		Status = HAL_BUSY;
	}
    HAL_DMA_DeInit(&hdma_sdio);
   hdma_sdio.Instance = DMA2_Channel4;
   hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH;
   hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
   hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
   hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
   hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
   hdma_sdio.Init.Mode = DMA_NORMAL;
   hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
   if(HAL_DMA_Init(&hdma_sdio) != HAL_OK)
   {
       Error_Handler();
   }

   __HAL_LINKDMA(&hmmc, hdmatx, hdma_sdio);
  if (HAL_MMC_WriteBlocks_DMA(&hmmc, pData, BlockAdd, NumberOfBlocks) != HAL_OK)
  {

    Status = HAL_ERROR;
  }
  return Status; 
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

EMMC测试

  	uint8_t recvbuf[512];
  	uint8_t sendbuf[512] = {0xAA,0xBB,0xCC,0xDD};
	printf("\r\n--------> EMMC DMA Test\r\n");
	ret= EMMC_ReadBlock_DMA(recvbuf,0,1);
	if(ret == HAL_OK)
	{
		for (uint16_t i = 0; i < BLOCKSIZE; i++)
    {
      printf("0x%02x ",recvbuf[i]);
      if((i%16) == 0)
      {
        printf("\r\n");
      }
    }
	}
	ret = EMMC_WriteBlock_DMA(sendbuf,0,1);
	if(ret == HAL_OK)
	{
		printf("\r\n--------> EMMC 写入成功\r\n");
	}
  ret =  EMMC_ReadBlock_DMA(recvbuf,0,1);
	printf("\r\n--------> ret:%d\r\n",ret);
  if(ret == HAL_OK)
  {
    for (uint16_t i = 0; i < hmmc.MmcCard.BlockSize; i++)
    {
      printf("0x%02x ",recvbuf[i]);
      if((i%16) == 0)
      {
        printf("\r\n");
      }
    }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

移植FATFS文件系统

准备工作

1.FATFS官网下载地址:http://elm-chan.org/fsw/ff/00index_e.html
2.截至2024.6.1最新版本为0.15
3.本工程使用版本为0.11a
  • 1
  • 2
  • 3

keil工程文件结构

在这里插入图片描述

修改底层驱动文件

底层驱动只需要修改diskio.c与ffconf.h
  • 1

修改ffconf.h

#define _USE_MKFS 1 // 0–>1
#define _CODE_PAGE 936 //932–>936 日文到中文
#define _USE_LFN 1 // 0->1 支持长文件名
#define _VOLUMES 1 //根据你使用的盘符数 自行更改
#define _MAX_SS 4096 // 512–>4096 SPI 扇区大小为4096
#define _FS_LOCK 3 // 0–>3 支持同时打开文件数 3个
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

添加底层驱动

disk_status
DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat = STA_NOINIT;
	if(pdrv == MMC)
	{
		printf("\r\n--------> disk_status EMMC\r\n");
		stat &= ~STA_NOINIT;
	}
	return stat;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
disk_initialize
DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat = STA_NOINIT;
	if(pdrv == MMC)
	{
		printf("\r\n--------> disk_initialize EMMC\r\n");
		if(HAL_MMC_Init(&hmmc)==HAL_OK)
		{
			printf("\r\n--------> disk_initialize EMMC Success\r\n");
			stat &= ~STA_NOINIT;
		}
	}
	return stat;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
disk_read
DRESULT disk_read (
	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
	BYTE *buff,		/* Data buffer to store read data */
	DWORD sector,	/* Sector address in LBA */
	UINT count		/* Number of sectors to read */
)
{
	DRESULT res;
	if(pdrv == MMC)
	{
		printf("\r\n--------> disk_read EMMC\r\n");
		if(EMMC_ReadBlock_DMA((uint8_t*)buff,(uint32_t)sector,count) == HAL_OK)
		{
			printf("\r\n--------> disk_read Success\r\n");
			res = RES_OK;
		}
		else
		{
			res = RES_PARERR;
		}
	}
	else
	{
		res = RES_ERROR;
	}
	return res;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
disk_write
DRESULT disk_write (
	BYTE pdrv,			/* Physical drive nmuber to identify the drive */
	const BYTE *buff,	/* Data to be written */
	DWORD sector,		/* Sector address in LBA */
	UINT count			/* Number of sectors to write */
)
{
	DRESULT res;
	if(pdrv == MMC)
	{
		printf("\r\n--------> disk_write EMMC\r\n");
		if(EMMC_WriteBlock_DMA((uint8_t*)buff,(uint32_t)sector,count) == HAL_OK)
		{
			printf("\r\n--------> disk_write Success\r\n");
			res = RES_OK;
		}
		else
		{
			res = RES_WRPRT;
		}
		
	}
	else
	{
		res = RES_ERROR;
	}
	return res;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
disk_ioctl
DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	DRESULT res = STA_NOINIT;
	int result;
	if(pdrv == MMC)
	{
		printf("\r\n--------> disk_ioctl EMMC\r\n");
		switch(cmd)
		{
			case GET_SECTOR_COUNT:
				*(DWORD * )buff = hmmc.MmcCard.BlockNbr;
				break;
			case GET_SECTOR_SIZE:
				*(DWORD * )buff = hmmc.MmcCard.BlockSize;
				break;
			case GET_BLOCK_SIZE:
				*(DWORD * )buff = 1;
				break;
			case MMC_GET_SDSTAT:
				*(DWORD * )buff = HAL_MMC_GetState(&hmmc);
				break;
		}
		res = RES_OK;
	}
	return RES_OK;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

FATFS文件挂载测试

FATFS fs;													/* FatFs文件系统对象 */
FIL fnew;													/* 文件对象 */
FRESULT res_sd;                /* 文件操作结果 */
UINT fnum;            					  /* 文件成功读写数量 */
BYTE ReadBuffer[1024]={0};        /* 读缓冲区 */
BYTE WriteBuffer[] = "Hello World!!!";         /* 写缓冲区*/
  printf("\r\n--------> EMMC 文件系统\r\n");
	res_sd = f_mount(&fs,"0:",1);
	
/*----------------------- 格式化测试 ---------------------------*/  
	/* 如果没有文件系统就格式化创建创建文件系统 */
	if(res_sd == FR_NO_FILESYSTEM)
	{
		printf("--------> EMMC还没有文件系统,即将进行格式化...\r\n");
    /* 格式化 */
		res_sd=f_mkfs("0:",0,0);							
		
		if(res_sd == FR_OK)
		{
			printf("--------> EMMC已成功格式化文件系统。\r\n");
      /* 格式化后,先取消挂载 */
			res_sd = f_mount(NULL,"0:",1);			
      /* 重新挂载	*/			
			res_sd = f_mount(&fs,"0:",1);
		}
		else
		{
			printf("--------> EMMC格式化失败\r\n");
			while(1);
		}
	}
  else if(res_sd!=FR_OK)
  {
    printf("--------> EMMC挂载文件系统失败:(%d)\r\n",res_sd);
    printf("--------> EMMC初始化不成功。\r\n");
		while(1);
  }
  else
  {
    printf("--------> EMMC文件系统挂载成功,可以进行读写测试\r\n");
  }
	printf("\r\n--------> EMMC即将进行文件写入\r\n");
	res_sd = f_open(&fnew, "0:FatFs1.txt",FA_CREATE_ALWAYS | FA_WRITE ); //ps:文件名不要过长,过长会导致创建失败,若过长需要在ffconf.h中开启宏定义
	if ( res_sd == FR_OK )
	{
		printf("--------> EMMC打开/创建FatFs1.txt文件成功,向文件写入数据。\r\n");
    /* 将指定存储区内容写入到文件内 */
		res_sd=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum);
    if(res_sd==FR_OK)
    {
      printf("--------> EMMC文件写入成功,写入字节数据:%d\n",fnum);
      printf("--------> EMMC向文件写入的数据为:\r\n%s\r\n",WriteBuffer);
    }
    else
    {
      printf("-------->EMMC文件写入失败:(%d)\n",res_sd);
    }    
		/* 不再读写,关闭文件 */
    f_close(&fnew);
	}
	else
	{	
		printf("--------> EMMC打开/创建文件失败\r\n");
	}
	
	printf("--------> EMMC即将进行文件读取\r\n");
	res_sd = f_open(&fnew, "0:FatFs1.txt", FA_OPEN_EXISTING | FA_READ); 	 
	if(res_sd == FR_OK)
	{
		printf("--------> EMMC打开文件成功。\r\n");
		res_sd = f_read(&fnew, ReadBuffer, sizeof(ReadBuffer), &fnum); 
    if(res_sd==FR_OK)
    {
      printf("--------> EMMC文件读取成功,读到字节数据:%d\r\n",fnum);
      printf("--------> EMMC读取得的文件数据为:\r\n%s \r\n", ReadBuffer);	
    }
    else
    {
      printf("--------> EMMC文件读取失败:(%d)\n",res_sd);
    }		
	}
	else
	{
		printf("--------> EMMC打开文件失败\r\n");
	}
	/* 不再读写,关闭文件 */
	f_close(&fnew);	
  
	/* 不再使用文件系统,取消挂载文件系统 */
	f_mount(NULL,"0:",1);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90

###测试结果
在这里插入图片描述

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号