【ZYNQ】SD 卡读写及文件扫描实验

news2024/12/22 23:49:47

SD 卡控制器(SD/SDIO Controller)

ZYNQ 中的 SD 卡控制器符合 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 设置中选中 xilffsxilffs 即为 FATFS 库,保存配置:

在这里插入图片描述

添加如下代码:

#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();
    scan_files(SD_FS);

    while(1)
    {

    }

    return 0;
}

实验现象

  • 终端输出:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1259183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【腾讯云云上实验室】用向量数据库——实现高效文本检索功能

文章目录 前言Tencent Cloud VectorDB 简介Tencent Cloud VectorDB 使用实战申请腾讯云向量数据库腾讯云向量数据库使用步骤腾讯云向量数据库实现文本检索 结论和建议 前言 想必各位开发者一定使用过关系型数据库MySQL去存储我们的项目的数据,也有部分人使用过非关…

vue3安装eslint和prettier,最简单的步骤

第1步: 安装eslint yarn add eslint -D 第2步: 在根文件夹中,创建.eslintrc.js文件 第3步: 在package.json文件中新增命令 "lint": "eslint --fix --ext .ts,.tsx,.vue src --quiet","prettier"…

编程学习及常见的技术难题

文章目录 编程学习及常见的技术难题引言如何学习编程学习参考开发工具推荐编程中常见的技术难题 编程学习及常见的技术难题 引言 学习编程是一件有趣也有挑战的事情,它可以让你创造出各种有用的软件,解决各种复杂的问题,甚至改变世界。 编程中…

数据结构与算法编程题30

层次遍历二叉树(队列&#xff1a;先进先出) #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std;typedef char ElemType; #define ERROR 0 #define OK 1 #define Maxsize 100 #define STR_SIZE 1024typedef struct BiTNode {ElemType data;BiTNode…

西南科技大学数字电子技术实验一(数字信号基本参数与逻辑门电路功能测试及FPGA 实现)FPGA部分

一、 实验目的 1、掌握基于 Verilog 语言的 diamond 工具设计全流程。 2、熟悉、应用 Verilog HDL 描述数字电路。 3、掌握 Verilog HDL 的组合和时序逻辑电路的设计方法。 4、掌握“小脚丫”开发板的使用方法。 二、 实验原理 与门逻辑表达式:Y=AB 原理仿真图: 2 输入…

Flask SocketIO 实现动态绘图

Flask-SocketIO 是基于 Flask 的一个扩展&#xff0c;用于简化在 Flask 应用中集成 WebSocket 功能。WebSocket 是一种在客户端和服务器之间实现实时双向通信的协议&#xff0c;常用于实现实时性要求较高的应用&#xff0c;如聊天应用、实时通知等&#xff0c;使得开发者可以更…

FreeRTOS源码阅读笔记6--event_groups.c

通常用的事件标志组是一个32位的变量uxEventBits&#xff0c;可设置的位有24位&#xff0c;一共就是24 种事件。 事件组的结构体类型&#xff1a; 6.1创建事件组xEventGroupCreate() 6.1.1函数原型 返回值&#xff1a;事件组句柄&#xff0c;指向事件组。 6.1.2函数框架 ①…

【牛客网】SQL必知必会题解

SQL 必知必会题解 地址&#xff1a;牛客网在线编程_SQL篇_SQL必知必会 (nowcoder.com) 检索数据 从 Customers 表中检索所有的 ID 现有表 Customers 如下&#xff1a; cust_idABC 【问题】编写 SQL 语句&#xff0c;从 Customers 表中检索所有的 cust_id 答案&#xff1a;…

HUAWEI WATCH 4系列腕上星球,智慧生活触手可得

腕上星球&#xff0c;智慧生活触手可得。HUAWEI WATCH 4系列星球表盘引领风潮&#xff0c;万能卡片轻松便捷开启应用&#xff0c;腕上微信聊天抬腕即回&#xff0c;更有超级快充助力畅玩。全能型智能手表&#xff0c;生活更出彩&#xff01;

JAVA将PDF转图片

前言 当今时代&#xff0c;PDF 文件已经成为了常用的文档格式。然而&#xff0c;在某些情况下&#xff0c;我们可能需要将 PDF 文件转换为图片格式&#xff0c;以便更方便地分享和使用。这时&#xff0c;我们可以使用 Java 编程语言来实现这个功能。Java 提供了许多库和工具&a…

MacOS 14 系统 XCode15、 Flutter 开发 IOS

Flutter 系列文章目录 MacOS14 Sonoma 安装 Flutter 开发环境 MacOS 系统 Flutter开发Android 环境配置MacOS 系统 Flutter开发IOS 环境配置​​​​​​​ 前言 前面我们已经在MacOS14 M3芯片上安装好 Flutter环境&#xff0c;包括开发工具 VsCode 、Android Stuiod,那么fl…

用函数初始化数组

将数组全部初始化为相同值 对于一般情况 一般是用函数&#xff0c;传什么数就初始化为什么数 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> void init(int arr[], int len, int num) {int i;for (i 0; i < len; i){arr[i] num;} } int main() {int arr[…

数据库第十第十一章 恢复和并发简答题

数据库第一章 概论简答题 数据库第二章 关系数据库简答题 数据库第三章 SQL简答题 数据库第四第五章 安全性和完整性简答题 数据库第七章 数据库设计简答题 数据库第九章 查询处理和优化简答题 1.什么是数据库中的事务&#xff1f;它有哪些特性&#xff1f;这些特性的含义是什么…

微服务--01--简介、服务拆分原则

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 微服务微服务架构&#xff0c;是服务化思想指导下的一套最佳实践架构方案。服务化&#xff0c;就是把单体架构中的功能模块拆分为多个独立项目。 单体架构微服务架构…

vscode Markdown 预览样式美化多方案推荐

优雅的使用 vscode写 Markdown&#xff0c;预览样式美化 1 介绍 我已经习惯使用 vscode 写 markdown。不是很喜欢他的 markdown 样式&#xff0c;尤其是代码块高亮的样式。当然用 vscode 大家基本上都会选择安装一个Markdown-preview-enhanced的插件&#xff0c;这个插件的确…

数字IC芯片验证流程及验证工具推荐?收藏专用

验证其实是一个“证伪”的过程&#xff0c;从流程到工具&#xff0c;验证工程师的终极目的都只有一个&#xff1a; 发现所有BUG&#xff0c;或者证明没有BUG&#xff0c;以保证芯片功能性能的正确性和可靠性。 验证环节对于一颗芯片的重要性也是不言而喻的&#xff1a; 从项…

甘草书店记:2023年10月10日 星期二 晴 「甘草书店从何而来」

甘草书店记&#xff1a;2023年10月10日 星期二 晴 「甘草书店从何而来」 甘草书店的落地&#xff0c;差不多是“一瞬间”实现的。 麦田医学和公司新址园区沟通办公室租赁细节时&#xff0c;园区负责人谈到了一楼大厅的咖啡馆计划&#xff0c;而我适时地提出了一些建议和我对于…

JAVA 算法面试总结

1、二分查找 二分查找又叫折半查找&#xff0c;要求待查找的序列有序。每次取中间位置的值与待查关键字比较&#xff0c;如果中间位置 的值比待查关键字大&#xff0c;则在前半部分循环这个查找的过程&#xff0c;如果中间位置的值比待查关键字小&#xff0c; 则在后半部分循环…

MySQL(主从复制)

简述&#xff1a;主从复制&#xff0c;是用来建立一个和主数据库完全一样的数据库环境&#xff0c;称为从数据库&#xff0c;主数据库一般是准实时的 业务数据库、事务处理库&#xff0c;从库做查询库。 复制过程简单的说就是 master 将数据库的改变写入二进制日志&#xff0c…

JOSEF电流继电器 DL-33 整定范围0.5-2A 柜内安装板前接线

系列型号&#xff1a; DL-31电流继电器; DL-32电流继电器; DL-33电流继电器; DL-34电流继电器; 一、用途 DL-30系列电流继电器用于电机保护、变压器保护和输电线的过负荷和短路保护线路中&#xff0c;作为起动元件。 二、结构和原理 继电器系电磁式&#xff0c;瞬时动作…