打印
[学习笔记]

AC781X基于SD卡的FATFS文件系统移植

[复制链接]
1350|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
环境准备
硬件:AC781X demo板, SD卡,卡套

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


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

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

        switch (pdrv) {
        case DEV_RAM :
                //result = RAM_disk_status();

                // translate the reslut code here
        stat = STA_NODISK;
                return stat;

        case DEV_SD :
                result = SD_disk_status();

                // translate the reslut code here
        if (result == 0)
        {
            stat = 0;
        }
        else
        {
            stat = STA_NODISK;
        }
                return stat;

        case DEV_USB :
                //result = USB_disk_status();

                // translate the reslut code here
        stat = STA_NODISK;

                return stat;
        }
        return STA_NOINIT;
}



/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
        BYTE pdrv                                /* Physical drive nmuber to identify the drive */
)
{
        DSTATUS stat;
        int result;

        switch (pdrv) {
        case DEV_RAM :
                //result = RAM_disk_initialize();

                // translate the reslut code here
        stat = STA_NODISK;

                return stat;

        case DEV_SD :
                result = SD_disk_initialize();

                // translate the reslut code here
        if (result == 0)
        {
            stat = 0;
        }
        else
        {
            stat = STA_NODISK;
        }
                return stat;

        case DEV_USB :
                //result = USB_disk_initialize();

                // translate the reslut code here
        stat = STA_NODISK;

                return stat;
        }
        return STA_NOINIT;
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
        BYTE pdrv,                /* Physical drive nmuber to identify the drive */
        BYTE *buff,                /* Data buffer to store read data */
        DWORD sector,        /* Start sector in LBA */
        UINT count                /* Number of sectors to read */
)
{
        DRESULT res;
        int result;

        switch (pdrv) {
        case DEV_RAM :
                // translate the arguments here

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

                // translate the reslut code here
        res = RES_ERROR;

                return res;

        case DEV_SD :
                // translate the arguments here

                result = SD_disk_read(buff, sector, count);

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

                return res;

        case DEV_USB :
                // translate the arguments here

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

                // translate the reslut code here
        res = RES_ERROR;

                return res;
        }

        return RES_PARERR;
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

#if FF_FS_READONLY == 0

DRESULT disk_write (
        BYTE pdrv,                        /* Physical drive nmuber to identify the drive */
        const BYTE *buff,        /* Data to be written */
        DWORD sector,                /* Start sector in LBA */
        UINT count                        /* Number of sectors to write */
)
{
        DRESULT res;
        int result;

        switch (pdrv) {
        case DEV_RAM :
                // translate the arguments here

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

                // translate the reslut code here
        res = RES_ERROR;

                return res;

        case DEV_SD :
                // translate the arguments here

                result = SD_disk_write(buff, sector, count);

                // translate the reslut code here
        if (result == 0)
        {
            res = RES_OK;
        }
        else
        {
            res = RES_ERROR;
        }
                return res;

        case DEV_USB :
                // translate the arguments here

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

                // translate the reslut code here
        res = RES_ERROR;

                return res;
        }

        return RES_PARERR;
}

#endif


/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

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

        switch (pdrv) {
        case DEV_RAM :

                // Process of the command for the RAM drive

                return res;

        case DEV_SD :

                // Process of the command for the SD/SD card
        switch(cmd)
            {
                    case CTRL_SYNC:
                                res = RES_OK;
                        break;         
                    case GET_SECTOR_SIZE:
                                *(DWORD*)buff = g_sdCardInfo.sectorSize;
                        res = RES_OK;
                        break;         
                    case GET_BLOCK_SIZE:
                                *(WORD*)buff = g_sdCardInfo.blockSize;
                        res = RES_OK;
                        break;         
                    case GET_SECTOR_COUNT:
                        *(DWORD*)buff = g_sdCardInfo.sectorCount;
                        res = RES_OK;
                        break;
                    default:
                        res = RES_PARERR;
                        break;
            }
                return res;

        case DEV_USB :

                // Process of the command the USB drive

                return res;
        }

        return RES_PARERR;
}

实现完成后,我们就可以使用FATfs中的函数了,官网上对每一个API接口都有详细注释,部分函数还提供了使用示例,我们可以从官网的示例上找寻我们需要的代码:
 while(SD_disk_initialize()!=0)//can not find SD card
        {
        mdelay(1000);
                printf("Please Check!      \r\n");
        }
    res = f_mount(&fs, "", 1);
    if (FR_OK != res)
    {
        printf("\r\nfirst mount disk error : %02x, format disk\r\n", res);
        res = f_mkfs("", FM_FAT32, 0, work, sizeof(work));
        if (FR_OK != res)
        {
            printf("\r\nformat disk error : %02x\r\n", res);
            return -1;
        }
        res = f_mount(&fs, "", 1);
        if (FR_OK != res)
        {
            printf("\r\nmount disk error : %02x\r\n", res);
            return -1;
        }
    }
    printf("\r\nmount disk success\r\n");
    strcpy(buff, "/");
    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)





使用特权

评论回复

相关帖子

沙发
jinglixixi| | 2020-6-1 10:29 | 只看该作者
本帖最后由 jinglixixi 于 2020-6-1 10:31 编辑

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






使用特权

评论回复
板凳
marginer| | 2020-6-1 16:03 | 只看该作者
jinglixixi 发表于 2020-6-1 10:29
编译了一下,不能通过不知是什么原因。

ff.o这个文件有吗,看起来里面少voltopart这个函数的实现,有引用编译进去吗

使用特权

评论回复
地板
jinglixixi| | 2020-6-2 14:02 | 只看该作者
好的,再试试。

使用特权

评论回复
5
JasonLee27|  楼主 | 2020-6-2 14:07 | 只看该作者
jinglixixi 发表于 2020-6-1 10:29
编译了一下,不能通过不知是什么原因。

#define FF_MULTI_PARTITION        0
在ffconf.h文件下找到上面这个宏,改为0就好了,应该是之前测试多分区功能的时候改了没改回来

使用特权

评论回复
6
jinglixixi| | 2020-6-2 14:10 | 只看该作者
JasonLee27 发表于 2020-6-2 14:07
#define FF_MULTI_PARTITION        0
在ffconf.h文件下找到上面这个宏,改为0就好了,应该是之前测试多分区功能 ...

好的多谢了!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

66

主题

415

帖子

11

粉丝