当前位置:   article > 正文

【ZYNQ】SD 卡读写及文件扫描实验_zynq unable to format fatfs

zynq unable to format fatfs

SD 卡控制器

ZYNQ 中的 SD 卡控制(SD/SDIO Controller)器符合 SD2.0 协议规范,接口兼容 eMMC、MMC3.31、SDIO2.0、SD2.0、SPI,支持 SDHC、SDHS 器件。

SD 卡控制器支持 SDMA(单操作 DMA)、ADMA1(4K 边界限制 DMA)和 ADMA2(在 32 位系统中允许任何位置和任意大小)。ARM 处理器通过 AHB 总线访问 SD 卡控制器,SD 控制器采用读和写通道各自双缓冲 FIFO 的机制提高吞吐带宽。

其内部框图如下图所示:

SD 控制器读写通道采用独立的 512 字节深度的双缓冲 FIFO 执行读和写操作。在写操作时,处理器向其中一个 FIFO 写数据,将另一个 FIFO 的数据写到 SD 总线;在读操作时,SD 总线上的数据向其中一个 FIFO 写数据,处理器将数据从另一个 FIFO 读出数据。SD 卡控制器通过双缓冲机制以保证最大带宽。

FATFS 文件系统

FATFS 是一个完全开源免费的 FAT 文件系统模块,专门为小型的嵌入式系统而设计。它完全用标准 C 语言编写,所以具有良好的硬件平台独立性,可以很方便的移植到各种嵌入式处理器中。

Xilinx SDK 的 standalone 已经移植好了 FATFS 文件系统,因此在 SDK 中添加 xilffs 库后,就可以在程序中使用 FATFS 中的 API 函数来操作 SD 卡。

FATFS 的特点如下:

  • 1、 结构清晰,代码量少,文件系统和 IO 底层分开,特别适合新手入门学习;
  • 2、 支持最多 10 个逻辑盘符和两级文件夹;
  • 3、 支持 FAT12/FAT16 和 FAT32 文件系统;
  • 4、 支持长文件名称。

FATFS 的这些特点,加上开源、免费的原则,使得 FATFS 的应用非常广泛。FATFS 模块的层次结构分为顶层、中间层 FATFS 模块和底层接口。

最顶层是应用层,使用者无需理会 FATFS 的内部结构和复杂的 FAT 协议,只需要调用 FATFS 模块提供给用户的一系列应用接口函数,如 f_open,f_read,f_write 和 f_close 等,就可以像在 PC 上读/写文件那样简单。

中间层 FATFS 模块,实现了 FAT 文件读/写协议。FATFS 模块提供的是 ff.c 和 ff.h。除非有必要,使用者一般不用修改,使用时将头文件直接包含进去即可。

FATFS 模块提供的底层接口,它包括存储媒介读/写接口(disk I/O)和供给文件创建修改时间的实时时钟。

读写实验

  • 实验平台:黑金 ZYNQ7035
  • 开发环境:Vivado 2017.4

硬件设计

  • 参考原理图可知,SD 卡接在了 PS_MIO40~45:

  • ZYNQ PS 做如下配置,配置 Bank 1 为 LVCMOS 1.8V,打开 UART0 和 SD0:

  • 完善其他配置后生成比特流,导出硬件信息即可。

软件设计

  • 创建 SDK 工程,在 BSP 设置中选中 xilffs

  • 点击左侧 xilffs。将 use_lfn 设置为 true,使能长文件名以及文件名的小写字母,点击 OK 按钮完成设置:

  • 在工程中添加以下代码:
#include "xparameters.h"
#include "ff.h"
#include "xdevcfg.h"
#include "xil_printf.h"
#include "stdio.h"

#define kprintf xil_printf

#define SD_FS   "0:/"
#define SD_FILE "0:SD_TEST.txt"

static FATFS sd_fatfs;

static FRESULT fatfs_init(FATFS *fatfs, TCHAR *path)
{
    FRESULT res;

    res = f_mount(fatfs, path, 1);
    if(res != FR_OK)
    {
        res = f_mkfs(path, 0, 0);
        if (res != FR_OK)
        {
            kprintf("ERROR: Unable to format FATfs.\r\n");
            return res;
        }

        res = f_mount(fatfs, path, 1);
        if(res != FR_OK)
        {
            kprintf("ERROR: f_mount returned %d.\r\n", res);
            return res;
        }
    }
    return res;
}

static FRESULT sd_read_data(char *FileName, uint32_t DestinationAddress, uint32_t ByteLength)
{
    FIL fil;
    FRESULT res;
    UINT br;

    res = f_open(&fil, FileName, FA_READ);
    if(res)
    {
        kprintf("ERROR: %s f_open returned %d\r\n", FileName, res);
        return res;
    }

    res = f_lseek(&fil, 0);
    if(res)
    {
        kprintf("ERROR: %s f_lseek returned %d\r\n", FileName, res);
        return res;
    }

    res = f_read(&fil, (void*)DestinationAddress, ByteLength, &br);
    if(res)
    {
        kprintf("ERROR: %s f_read returned %d\r\n", FileName, res);
        return res;
    }

    res = f_close(&fil);
    if(res)
    {
        kprintf("ERROR: %s f_close returned %d\r\n", FileName, res);
        return res;
    }
    return res;
}

static FRESULT sd_write_data(char *FileName, uint32_t SourceAddress, uint32_t ByteLength)
{
    FIL fil;
    FRESULT res;
    UINT bw;

    res = f_open(&fil, FileName, FA_CREATE_ALWAYS | FA_WRITE);
    if(res)
    {
        kprintf("ERROR: %s f_open returned %d.\r\n", FileName, res);
        return res;
    }

    res = f_lseek(&fil, 0);
    if(res)
    {
        kprintf("ERROR: %s f_lseek returned %d.\r\n", FileName, res);
        return res;
    }

    res = f_write(&fil, (void*) SourceAddress, ByteLength, &bw);
    if(res)
    {
        kprintf("ERROR: %s f_write returned %d.\r\n", FileName, res);
        return res;
    }

    res = f_close(&fil);
    if(res)
    {
        kprintf("ERROR: %s f_close returned %d.\r\n", FileName, res);
        return res;
    }
    return res;
}

static FRESULT sd_rw_test(void)
{
    FRESULT res;
    const char src_str[] = "ZYNQ test SD card write and read!";
    char dest_str[33];
    uint32_t len = strlen(src_str);

    res = sd_write_data(SD_FILE, (uint32_t)src_str, len);
    if(XST_SUCCESS != res)
    {
        kprintf("ERROR: fail to write SD Card.\r\n");
        return res;
    }
    else
    {
        kprintf("Success to write SD Card.\r\n");
    }

    res = sd_read_data(SD_FILE, (uint32_t)dest_str, len);
    if(XST_SUCCESS != res)
    {
        kprintf("ERROR: fail to read SD Card.\r\n");
        return res;
    }
    else
    {
        kprintf("Success to read SD Card; data: %s \r\n", dest_str);
    }

    kprintf("SD Card Write and Read test end.\r\n");
    return res;
 }

static FRESULT scan_files(char *path)
{
    FRESULT res;
    DIR dir;
    UINT i;
    static FILINFO fno;

    res = f_opendir(&dir, path);

    char pathBuff[256];

    if(res == FR_OK)
    {
        for( ; ; )
        {
            res = f_readdir(&dir, &fno);
            if(res != FR_OK || fno.fname[0] == 0)
            {
                break;
            }

            if(fno.fattrib & AM_DIR)
            {
                i = strlen(path);
                sprintf(&path[i], "/%s", fno.fname);
                kprintf("%s \r\n", path);
                res = scan_files(path);
                if(res != FR_OK)
                {
                    break;
                }
                path[i] = 0;
            }
            else
            {
                kprintf("%s/%s \r\n", path, fno.fname);
                strcpy(pathBuff, fno.fname);
            }
        }
    }
    else
    {
        kprintf("Failed - %s", &res);
    }
    f_closedir(&dir);
    return res;
}

int main(void)
{
    kprintf("hello world. \r\n");

    FRESULT res;

    res = fatfs_init(&sd_fatfs, SD_FS);
    if(XST_SUCCESS != res)
    {
        kprintf("ERROR: fail to open SD Card.\r\n");
    }
    else
    {
        kprintf("Success to open SD Card.\r\n");
    }

    sd_rw_test();

    kprintf("Scan Files in %s: \r\n", SD_FS);
    
    scan_files(SD_FS);

    while(1)
    {

    }

    return 0;
}
  • 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
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219

实验现象

  • 终端输出:

  • 查看 SD 卡:

参考来源

  • 正点原子领航者
  • 黑金 ZYNQ7035

更多内容

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/465481
推荐阅读
相关标签
  

闽ICP备14008679号