[学习笔记] AC781X基于SD卡的FATFS文件系统移植

[复制链接]
1626|5
 楼主| JasonLee27 发表于 2019-7-15 14:24 | 显示全部楼层 |阅读模式
环境准备
硬件:AC781X demo板, SD卡,卡套

软件: Keil5.2.3
因为AC781X不支持SDIO,所以我们要采用SPI方式与SD卡通信,SPI有4线,加上电源线总共六根线,下图是我焊好的接线(千万不要直接在SD卡上焊,不然SD卡就焊废了)
WeChat Image_20190715134743.jpg

1,首先从网上下载最新的FATFS文件系统源码http://elm-chan.org/fsw/ff/00index_e.html,本贴用的是R0.13c版本

2,新建一个keil工程,并在工程下新建一个FATfs文件夹,将下载的文件解压到该文件夹下

3,按官方的文档,我们只需要移植实现diskio.c中的函数即可;这里,我们需要实现diskio.c的底层操作,这里我用了两个文件,一个spi.c用于实现底层SPI的初始化和读写操作,一个sdcard.c用于实现对SD卡的操作封装。整体的工程框架如下:

这里将下diskio.c的一些修改部分:
  1. /* Definitions of physical drive number for each drive */
  2. #define DEV_SD                0        /* Example: Map SD/SD card to physical drive 1 */
  3. #define DEV_RAM                1        /* Example: Map Ramdisk to physical drive 0 */
  4. #define DEV_USB                2        /* Example: Map USB MSD to physical drive 2 */
文件默认设置了三种存储系统,SD,RAM以及USB,我们使用的是SD,为了方便操作,我们将SD改为物理驱动0;

接下来就是实现后面的几个函数了,按照官方对函数的说明,我们调用自己的程序,并将自己的值与FATfs的值进行转化:
  1. DSTATUS disk_status (
  2.         BYTE pdrv                /* Physical drive nmuber to identify the drive */
  3. )
  4. {
  5.         DSTATUS stat;
  6.         int result;

  7.         switch (pdrv) {
  8.         case DEV_RAM :
  9.                 //result = RAM_disk_status();

  10.                 // translate the reslut code here
  11.         stat = STA_NODISK;
  12.                 return stat;

  13.         case DEV_SD :
  14.                 result = SD_disk_status();

  15.                 // translate the reslut code here
  16.         if (result == 0)
  17.         {
  18.             stat = 0;
  19.         }
  20.         else
  21.         {
  22.             stat = STA_NODISK;
  23.         }
  24.                 return stat;

  25.         case DEV_USB :
  26.                 //result = USB_disk_status();

  27.                 // translate the reslut code here
  28.         stat = STA_NODISK;

  29.                 return stat;
  30.         }
  31.         return STA_NOINIT;
  32. }



  33. /*-----------------------------------------------------------------------*/
  34. /* Inidialize a Drive                                                    */
  35. /*-----------------------------------------------------------------------*/

  36. DSTATUS disk_initialize (
  37.         BYTE pdrv                                /* Physical drive nmuber to identify the drive */
  38. )
  39. {
  40.         DSTATUS stat;
  41.         int result;

  42.         switch (pdrv) {
  43.         case DEV_RAM :
  44.                 //result = RAM_disk_initialize();

  45.                 // translate the reslut code here
  46.         stat = STA_NODISK;

  47.                 return stat;

  48.         case DEV_SD :
  49.                 result = SD_disk_initialize();

  50.                 // translate the reslut code here
  51.         if (result == 0)
  52.         {
  53.             stat = 0;
  54.         }
  55.         else
  56.         {
  57.             stat = STA_NODISK;
  58.         }
  59.                 return stat;

  60.         case DEV_USB :
  61.                 //result = USB_disk_initialize();

  62.                 // translate the reslut code here
  63.         stat = STA_NODISK;

  64.                 return stat;
  65.         }
  66.         return STA_NOINIT;
  67. }



  68. /*-----------------------------------------------------------------------*/
  69. /* Read Sector(s)                                                        */
  70. /*-----------------------------------------------------------------------*/

  71. DRESULT disk_read (
  72.         BYTE pdrv,                /* Physical drive nmuber to identify the drive */
  73.         BYTE *buff,                /* Data buffer to store read data */
  74.         DWORD sector,        /* Start sector in LBA */
  75.         UINT count                /* Number of sectors to read */
  76. )
  77. {
  78.         DRESULT res;
  79.         int result;

  80.         switch (pdrv) {
  81.         case DEV_RAM :
  82.                 // translate the arguments here

  83.                 //result = RAM_disk_read(buff, sector, count);

  84.                 // translate the reslut code here
  85.         res = RES_ERROR;

  86.                 return res;

  87.         case DEV_SD :
  88.                 // translate the arguments here

  89.                 result = SD_disk_read(buff, sector, count);

  90.                 // translate the reslut code here
  91.         res = result==0?RES_OK:RES_ERROR;

  92.                 return res;

  93.         case DEV_USB :
  94.                 // translate the arguments here

  95.                 //result = USB_disk_read(buff, sector, count);

  96.                 // translate the reslut code here
  97.         res = RES_ERROR;

  98.                 return res;
  99.         }

  100.         return RES_PARERR;
  101. }



  102. /*-----------------------------------------------------------------------*/
  103. /* Write Sector(s)                                                       */
  104. /*-----------------------------------------------------------------------*/

  105. #if FF_FS_READONLY == 0

  106. DRESULT disk_write (
  107.         BYTE pdrv,                        /* Physical drive nmuber to identify the drive */
  108.         const BYTE *buff,        /* Data to be written */
  109.         DWORD sector,                /* Start sector in LBA */
  110.         UINT count                        /* Number of sectors to write */
  111. )
  112. {
  113.         DRESULT res;
  114.         int result;

  115.         switch (pdrv) {
  116.         case DEV_RAM :
  117.                 // translate the arguments here

  118.                 //result = RAM_disk_write(buff, sector, count);

  119.                 // translate the reslut code here
  120.         res = RES_ERROR;

  121.                 return res;

  122.         case DEV_SD :
  123.                 // translate the arguments here

  124.                 result = SD_disk_write(buff, sector, count);

  125.                 // translate the reslut code here
  126.         if (result == 0)
  127.         {
  128.             res = RES_OK;
  129.         }
  130.         else
  131.         {
  132.             res = RES_ERROR;
  133.         }
  134.                 return res;

  135.         case DEV_USB :
  136.                 // translate the arguments here

  137.                 //result = USB_disk_write(buff, sector, count);

  138.                 // translate the reslut code here
  139.         res = RES_ERROR;

  140.                 return res;
  141.         }

  142.         return RES_PARERR;
  143. }

  144. #endif


  145. /*-----------------------------------------------------------------------*/
  146. /* Miscellaneous Functions                                               */
  147. /*-----------------------------------------------------------------------*/

  148. DRESULT disk_ioctl (
  149.         BYTE pdrv,                /* Physical drive nmuber (0..) */
  150.         BYTE cmd,                /* Control code */
  151.         void *buff                /* Buffer to send/receive control data */
  152. )
  153. {
  154.         DRESULT res;

  155.         switch (pdrv) {
  156.         case DEV_RAM :

  157.                 // Process of the command for the RAM drive

  158.                 return res;

  159.         case DEV_SD :

  160.                 // Process of the command for the SD/SD card
  161.         switch(cmd)
  162.             {
  163.                     case CTRL_SYNC:
  164.                                 res = RES_OK;
  165.                         break;         
  166.                     case GET_SECTOR_SIZE:
  167.                                 *(DWORD*)buff = g_sdCardInfo.sectorSize;
  168.                         res = RES_OK;
  169.                         break;         
  170.                     case GET_BLOCK_SIZE:
  171.                                 *(WORD*)buff = g_sdCardInfo.blockSize;
  172.                         res = RES_OK;
  173.                         break;         
  174.                     case GET_SECTOR_COUNT:
  175.                         *(DWORD*)buff = g_sdCardInfo.sectorCount;
  176.                         res = RES_OK;
  177.                         break;
  178.                     default:
  179.                         res = RES_PARERR;
  180.                         break;
  181.             }
  182.                 return res;

  183.         case DEV_USB :

  184.                 // Process of the command the USB drive

  185.                 return res;
  186.         }

  187.         return RES_PARERR;
  188. }

实现完成后,我们就可以使用FATfs中的函数了,官网上对每一个API接口都有详细注释,部分函数还提供了使用示例,我们可以从官网的示例上找寻我们需要的代码:
  1. while(SD_disk_initialize()!=0)//can not find SD card
  2.         {
  3.         mdelay(1000);
  4.                 printf("Please Check!      \r\n");
  5.         }
  6.     res = f_mount(&fs, "", 1);
  7.     if (FR_OK != res)
  8.     {
  9.         printf("\r\nfirst mount disk error : %02x, format disk\r\n", res);
  10.         res = f_mkfs("", FM_FAT32, 0, work, sizeof(work));
  11.         if (FR_OK != res)
  12.         {
  13.             printf("\r\nformat disk error : %02x\r\n", res);
  14.             return -1;
  15.         }
  16.         res = f_mount(&fs, "", 1);
  17.         if (FR_OK != res)
  18.         {
  19.             printf("\r\nmount disk error : %02x\r\n", res);
  20.             return -1;
  21.         }
  22.     }
  23.     printf("\r\nmount disk success\r\n");
  24.     strcpy(buff, "/");
  25.     res = scan_files(buff);
这里我自己先调用了SD_disk_initialize函数确保能找到SD卡(实测有时候总会检测不到,不知道是不是因为SD卡和卡套之间接触问题还是焊接问题,需要插拔一下SD卡才行)。
在检测到SD卡后调用f_mount函数挂载SD卡,如果失败了,表示SD卡没有格式化,则将SD卡先格式化,再重新挂载。这里实现了一个scan_files函数,可以遍历SD卡中的所有文件。这里就不在赘述。

最后附上实现代码: FATFS_sample.rar (1.96 MB, 下载次数: 108)





jinglixixi 发表于 2020-6-1 10:29 | 显示全部楼层
本帖最后由 jinglixixi 于 2020-6-1 10:31 编辑

编译了一下,不能通过不知是什么原因。

360截图1641011884102127.jpg


360截图16671021428440.jpg

marginer 发表于 2020-6-1 16:03 | 显示全部楼层
jinglixixi 发表于 2020-6-1 10:29
编译了一下,不能通过不知是什么原因。

ff.o这个文件有吗,看起来里面少voltopart这个函数的实现,有引用编译进去吗
jinglixixi 发表于 2020-6-2 14:02 | 显示全部楼层
好的,再试试。
 楼主| JasonLee27 发表于 2020-6-2 14:07 | 显示全部楼层
jinglixixi 发表于 2020-6-1 10:29
编译了一下,不能通过不知是什么原因。

#define FF_MULTI_PARTITION        0
在ffconf.h文件下找到上面这个宏,改为0就好了,应该是之前测试多分区功能的时候改了没改回来
jinglixixi 发表于 2020-6-2 14:10 | 显示全部楼层
JasonLee27 发表于 2020-6-2 14:07
#define FF_MULTI_PARTITION        0
在ffconf.h文件下找到上面这个宏,改为0就好了,应该是之前测试多分区功能 ...

好的多谢了!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

66

主题

415

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部