【超级详细】基于Zynq FPGA对雷龙SD NAND的测试

在这里插入图片描述

目录

    • 一、SD NAND特征
      • 1.1 SD卡简介
      • 1.2 SD卡Block图
    • 二、SD卡样片
    • 三、Zynq测试平台搭建
      • 3.1 测试流程
      • 3.2 SOC搭建

一、SD NAND特征

1.1 SD卡简介

雷龙的SD NAND有很多型号,在测试中使用的是CSNP4GCR01-AMW与CSNP32GCR01-AOW。芯片是基于NAND FLASH和 SD控制器实现的SD卡。具有强大的坏块管理和纠错功能,并且在意外掉电的情况下同样能保证数据的安全。

其特点如下:

接口支持SD2.0 2线或4线;

电压支持:2.7V-3.6V;

默认模式:可变时钟速率0 - 25MHz,高达12.5 MB/s的接口速度(使用4条并行数据线)

高速模式:可变时钟速率0 - 50MHz,高达25 MB/s的接口速度(使用4条并行数据线)

工作温度:-40°C ~ +85°C

存储温度:-55°C ~ +125°C

待机电流小于250uA

修正内存字段错误;

内容保护机制——符合SDMI最高安全标准

SDNAND密码保护(CMD42 - LOCK_UNLOCK)

采用机械开关的写保护功能

内置写保护功能(永久和临时)

应用程序特定命令

舒适擦除机制

该SD卡支持SDIO读写和SPI读写,最高读写速度可达25MB/s,实际读写速度要结合MCU和接口情况实测获得。通常在简单嵌入式系统并对读写速度要求不高的情况下,会使用SPI协议进行读写。但不管使用SDIO还是SPI都需要符合相关的协议规范,才能建立相应的文件系统;

1.2 SD卡Block图

SD卡Block图
在这里插入图片描述

该SD卡封装为LGA-8;引脚分配与定义如下;

在这里插入图片描述

SD卡封装为LGA-8引脚分配与定义

二、SD卡样片

与样片同时寄来的还有转接板,转接板将LGA-8封装的芯片转接至SD卡封装,这样只需将转接板插入SD卡卡槽即可使用。

在这里插入图片描述:

CS创世SD NAND转接板

在这里插入图片描述

三、Zynq测试平台搭建

测试平台为 Xilinx 的Zynq 7020 FPGA芯片;

板卡:Digilent Zybo Z7

Vivado版本:2018.3

文件系统:FATFS

SD卡接口:SD2.0

3.1 测试流程

本次测试主要针对4G和32G两个不同容量的SD卡,在Zynq FPGA上搭建SD卡读写回路,从而对SD卡读写速度进行测试,并检验读写一致性;

测试流程:

进入测试程序前,首先会对SD卡初始化并初始化建立FATFS文件系统,随后进入测试SD卡测试程序,在测试程序中,会写入一定大小的文件,然后对写入文件的时间进行测量,得到写入时间;然后再将写入的文件读出,测量获得读出时间,并将读出数据与写入数据相比较,检测是否读写出错。

通过写入时间、读出时间可计算得到写入速度、读出速度;将以上过程重复100次并打印报告。
  在这里插入图片描述

在Zynq FPGA上搭建SD卡读写回路

3.2 SOC搭建

硬件搭建框图如下,我们在本次系统中使用PS端的SDIO接口来驱动SD NAND芯片,并通过UART向PC打印报告;
在这里插入图片描述

PL端的硬件搭建也很简单,只需一个Timer定时器来做时间测量;

SD NAND(SD卡)PL端的硬件搭建

我们直接使用Zybo板卡文件创建一个工程,工程会将Zybo具有的硬件资源配置好;
在这里插入图片描述

Zybo板卡文件创建

首先点击setting->IP->Repository->+;添加Timer IP核的路径,Timer IP核会在工程中给出;
在这里插入图片描述

SOC搭建

点击Create Block Design创建BD工程
在这里插入图片描述

Create Block Design创建BD工程

在创建的过程中添加Zynq 内核;
在这里插入图片描述

SD NAND添加Zynq 内核

   由于我们使用了板卡文件,所以内核IP是配置好的,我们只需稍作修改即可,如果是其他板卡,则需要自行配置DDR等配置;

双击内核IP,点击Clock Configuration->PL Fabric Clocks,将FCLK_CLK0的时钟频率修改为100Mhz
  在这里插入图片描述

添加TimerA IP;
在这里插入图片描述

依次点击上方的自动设计,完成SOC搭建;
在这里插入图片描述

SOC搭建

点击BD设计,并创建顶层文件
在这里插入图片描述

SD NAND的SOC搭建

生成比特流文件;
在这里插入图片描述

SD NAND的SOC搭建 比特流文件

   在生成比特流文件后,将其导入SDK;

点击Export->Export Hardware,导出硬件;然后点击Launch SDK打开SDK进行软件设计;
  在这里插入图片描述
在这里插入图片描述

Export->Export Hardware,导出硬件Launch SDK打开SDK进行软件设计

四、软件搭建
  在SDK中新建一个空白工程;

点击file -> new -> Application project;
  在这里插入图片描述

SD NAND软件搭建

在新建的过程中创建一个main.c文件,并在里面编写测试程序如下:

在每次读写开始前,通过TimerA0_start()函数开始计时,在读写结束后可以通过TimerA0_stop()结束计时,从而测得消耗时间。

相应的Timer驱动函数在user/TimerA_user.c中定义;

#include "xparameters.h"    /* SDK generated parameters */

#include "xsdps.h"        /* SD device driver */

#include "xil_printf.h"

#include "ff.h"

#include "xil_cache.h"

#include "xplatform_info.h"

#include "time.h"

#include "../user/headfile.h"



#define    PACK_LEN       32764



static FIL fil;        /* File object */

static FATFS fatfs;



static char FileName[32] = "Test.txt";

static char *SD_File;



char DestinationAddress[PACK_LEN] ;



char txt[1024];

char test_buffer[PACK_LEN];



void TimerA0_init()

{

    TimerA_reset(TimerA0);//reset timerA device

    TimerA_Set_Clock_Division(TimerA0,100);//divide clock as 100000000/100 = 1Mhz

    TimerA_Stop_Counter(TimerA0);//stop timerA

}



void TimerA0_start()

{

    TimerA_SetAs_CONTINUS_Mode(TimerA0);

}



void TimerA0_stop()

{

    TimerA_Stop_Counter(TimerA0);

}









uint32 SDCard_test()

{

    uint8 Res;

    uint32 NumBytesRead;

    uint32 NumBytesWritten;

    uint32 BuffCnt;

    uint8 work[FF_MAX_SS];

    uint32 take_time=0;

    uint32 speed = 0;

    uint32 test_time = 0;

    uint32 w_t=0;

    uint32 r_t=0;

    float wsum = 0;

    float rsum = 0;





    TCHAR *Path = "0:/";



    for(int i=0;i<PACK_LEN;i++)

    {

        test_buffer[i] = 'a';

    }



    Res = f_mount(&fatfs, Path, 0);



    if (Res != FR_OK) {

        return XST_FAILURE;

    }



    Res = f_mkfs(Path, FM_FAT32, 0, work, sizeof work);

    if (Res != FR_OK) {

        return XST_FAILURE;

    }



    SD_File = (char *)FileName;



    Res = f_open(&fil, SD_File, FA_CREATE_ALWAYS | FA_WRITE | FA_READ);

    if (Res) {

        return XST_FAILURE;

    }



    Res = f_lseek(&fil, 0);

    if (Res) {

        return XST_FAILURE;

    }



    while(1)

    {

        TimerA_reset(TimerA0);

        TimerA0_start();

        Res = f_write(&fil, (const void*)test_buffer, PACK_LEN,

                &NumBytesWritten);

        TimerA0_stop();

        take_time = TimerA_Read_Counter_Register(TimerA0);

        w_t+=take_time;

        xil_printf("--------------------------------\n");

        xil_printf("take time:%d us\n",take_time);

        speed = PACK_LEN*(1000000/((float)(take_time)));

        sprintf(txt,"write speed:%.2f MB/s\n",(float)(speed)/1024/1024);

        wsum = wsum+speed;

        xil_printf(txt);

        xil_printf("--------------------------------\n");

        if (Res) {

            return XST_FAILURE;

        }



        Res = f_lseek(&fil, 0);

        if (Res) {

            return XST_FAILURE;

        }



        TimerA_reset(TimerA0);

        TimerA0_start();

        Res = f_read(&fil, (void*)DestinationAddress, PACK_LEN,

                &NumBytesRead);

        TimerA0_stop();

        take_time = TimerA_Read_Counter_Register(TimerA0);

        r_t+=take_time;

        xil_printf("--------------------------------\n");

        xil_printf("take time:%d us\n",take_time);

        speed = PACK_LEN*(1000000/((float)(take_time)));

        sprintf(txt,"read speed:%.2f MB/s\n",(float)(speed)/1024/1024);

        rsum = rsum+speed;

        xil_printf(txt);

        xil_printf("--------------------------------\n");

        if (Res) {

            return XST_FAILURE;

        }





        for(BuffCnt = 0; BuffCnt < PACK_LEN; BuffCnt++){

            if(test_buffer[BuffCnt] != DestinationAddress[BuffCnt]){

                xil_printf("%dno",BuffCnt);

                return XST_FAILURE;

            }

        }

        xil_printf("test num:%d data check right!\n",test_time+1);

        test_time++;

        if(test_time==100)

        {

            sprintf(txt,"Total write: %.2f KB,Take time:%.2f ms, Write speed:%.2f MB/s\n",PACK_LEN*100/1024.0,w_t/100.0/1000.0,wsum/100/1024/1024);

            xil_printf(txt);

            sprintf(txt,"Total read: %.2f KB,Take time:%.2f ms, Read speed:%.2f MB/s\n",PACK_LEN*100/1024.0,r_t/100.0/1000.0,rsum/100/1024/1024);

            xil_printf(txt);

            Res = f_close(&fil);

            if (Res) {

                return XST_FAILURE;

            }

            return 0;

        }

    }



}



int main(void)

{

    TimerA0_init();



    SDCard_test();

    xil_printf("finish");

    return 0;

}

五、测试结果
  经测试,两种型号的芯片读写速度如下图表所示。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

其SD NAND的读写速度随着读写数据量的增加而增加,并且读速率大于写速率,这符合SD卡的特性;

对比两种型号SD NAND芯片,发现CSNP32GCR01-AOW型号具有更高的读写速度;

SD NAND的读写速度数据

SD NAND的写入速度数据SD NAND的读出速度数据

六、总结
  本来打算拿这些样片去试试信息安全领域是否有所应用,但发现其似乎内置了复位或初始化,导致无法提取上电时的不确定值,故无法提取该SD NAND的物理不可克隆特性,所以这方面的测试无法进行;

对于芯片正常读写的测试结果,还是很让人满意的,芯片的价格也很合理。并且LGA-8封装更适合无卡槽的嵌入式开发板设计,在一定的应用领域有着简化硬件设计、减小硬件面积的功能。

最后贴上测试工程的链接,还迎复现实验: https://gitee.com/gewenjie_host/sd_-nand_-zynq700_test

详细了解可以点击这里:点我查看

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python中常见的8种数据结构之一列表

列表是Python中最常见的数据结构之一。它是一种有序的集合&#xff0c;可以包含不同类型的数据。 以下是列表的一些特点和常见操作&#xff1a; 1. 定义列表&#xff1a;可以使用方括号&#xff08;[]&#xff09;来定义一个空列表&#xff0c;也可以在方括号中添加元素来初始…

Python 在PDF中绘制形状(线条、矩形、椭圆形等)

在PDF中绘制图形可以增强文档的视觉效果。通过添加不同类型的形状&#xff0c;如实线、虚线、矩形、圆形等&#xff0c;可以使文档更加生动有趣&#xff0c;提高读者的阅读兴趣。这对于制作报告、演示文稿或是教材特别有用。本文将通过以下几个示例介绍如何使用Python 在PDF中绘…

AndroidStudio-滚动视图ScrollView

滚动视图 滚动视图有两种: 1.ScrollView&#xff0c;它是垂直方向的滚动视图;垂直方向滚动时&#xff0c;layout_width属性值设置为match_parent&#xff0c;layout_height属性值设置为wrap_content。 例如&#xff1a; &#xff08;1&#xff09;XML文件中: <?xml ve…

【后端速成Vue】computed计算属性

前言&#xff1a; 本期将会介绍 Vue 中的计算属性&#xff0c;他和 methods 方法又会有什么区别呢&#xff1f;在这里都会给你一一讲解。 篮球哥找工作专属IT岗位内部推荐&#xff1a; 专属内推链接&#xff1a;内推通道 1、computed计算属性 概念&#xff1a; 基于现有的数据…

mysql 配置文件 my.cnf 增加 lower_case_table_names = 1 服务启动不了的原因

原因&#xff1a;在MySQL8.0之后的版本&#xff0c;只允许在数据库初始化时指定&#xff0c;之后不允许修改了 mysql 配置文件 my.cnf 增加 lower_case_table_names 1 服务启动不了 报错信息&#xff1a;Job for mysqld.service failed because the control process exited …

优化时钟网络之时钟偏移

Note&#xff1a;文章内容以Xilinx 7系列FPGA进行讲解 1、基本介绍 所谓时钟偏移&#xff08;Clock Skew&#xff09;&#xff0c;是指在同步时序电路中&#xff0c;同一个时钟信号到达各个寄存器时钟端口的时间不一致的现象。如下图所示&#xff1a; 时钟从源端到达寄存器FF1的…

npm镜像的常用操作

查看当前配置的 npm 镜像 npm config get registry切换官方镜像 npm config set registry https://registry.npmjs.org/切换淘宝镜像(推荐) npm config set registry https://registry.npmmirror.com/切换腾讯云镜像 npm config set registry http://mirrors.cloud.tencent…

Notepad++ 最新官网中文版在线下载 附文本编辑器安装与基础使用教程

Notepad &#xff08;记事本&#xff09;是一个简单的文本编辑器&#xff0c;预装在所有版本的 Microsoft Windows 操作系统中。它的主要功能是创建、编辑和存储纯文本文件&#xff0c;通常以 .txt 格式保存。Notepad 的设计旨在提供一个轻量级的文本处理工具&#xff0c;适合快…

Deprecated Gradle features were used in this build

前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 今天我使用gradle搭建springboot项目使用&#xff0c;报警告Deprecated Gradle features were used in this build, making it inco…

crond 任务调度 (Linux相关指令:crontab)

相关视频链接 crontab 进行 定时任务 的设置 概述 任务调度&#xff1a;是指系统在某个时间执行的特定的命令或程序 任务调度的分类&#xff1a; 1.系统工作&#xff1a;有些重要的工作必须周而复始地执行。如病毒扫描等。 2.个别用户可能希望执行某些程序&#xff0c;比如…

比流计算资源效率最高提升 1000 倍,“增量计算”新模式能否颠覆数据分析?

作者 | 关涛 云器科技CTO 数据平台领域发展 20 年&#xff0c;逐渐成为每个企业的基础设施。作为一个进入“普惠期”的领域&#xff0c;当下的架构已经完美了吗&#xff0c;主要问题和挑战是什么&#xff1f;在 2023 年 AI 跃变式爆发的大背景下&#xff0c;数据平台又该如何演…

区块链技术在供应链管理中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 区块链技术在供应链管理中的应用 区块链技术在供应链管理中的应用 区块链技术在供应链管理中的应用 引言 区块链技术概述 定义与…

微搭低代码入门01变量

目录 1 变量的定义2 变量的赋值3 变量的类型4 算术运算符5 字符串的连接6 模板字符串7 检查变量的类型8 解构赋值8.1 数组的解构赋值8.2 对象的解构赋值 9 类型转换9.1 转换为字符串9.2 转换为数字9.3 转换为布尔值 总结 好些零基础的同学&#xff0c;在使用低代码的时候&#…

大数据机器学习算法与计算机视觉应用04:多项式

The Algorithm Magic of Polynomial PolynomialsThe Root of PolynomialA Delete ChannelPolynomials for Finding Maximum Matchings Polynomials 多项式 一个 d d d 次多项式可以用一个 d 1 d1 d1 元组 c i {c_i} ci​ 表达。在这种情况下&#xff0c;两个多项式相加的…

【Vue】Vue3.0(十九)Vue 3.0 中一种组件间通信方式-自定义事件

文章目录 一、自定义事件概念及使用场景二、代码解释三、新的示例 一、自定义事件概念及使用场景 概念 在 Vue 3.0 中&#xff0c;自定义事件是一种组件间通信的机制&#xff0c;允许子组件向父组件传递数据或触发父组件中的操作。子组件通过defineEmits函数定义可以触发的事件…

单片机入门知识

1单片机系统的int是16位 计算机系统的int是32位&#xff08;数据总线&#xff09; 2的16次方是65536 所以在单片机中&#xff0c;如果表示一个正整数&#xff0c;这个数字的范围是0~65535&#xff0c;总共有65536种可能 2内存条用于存储计算机运行时的数据&#xff0c;是连接…

【高等数学】6向量与空间几何

1. 向量及其运算 1.1. 单向量的计算 向量的模的计算 单位向量的计算 1. 计算模: 2. 向量除以它的模: 1.2. 向量的点乘 点乘的计算 点乘:算出来的是一个数,所以点乘又称为向量的数量积。 向量点乘的计算公式: 向量的夹角计算 向量的夹角公式: 向量间平行垂直的…

Linux进程信号(信号的产生)

目录 什么是信号&#xff1f; 信号的产生 信号产生方式1&#xff1a;键盘 前台进程 后台进程 查看信号 signal系统调用 案例 理解进程记录信号 软件层面 硬件层面 信号产生方式2:指令 信号产生方式3:系统调用 kill系统调用 案例 其他产生信号的函数调用 1.rais…

7.qsqlquerymodel 与 qtableview使用

目录 qtableview 委托QStyledItemDelegateQAbstractItemDelegateCheckBoxItemDelegate使用qtableview控制列宽&#xff0c;行高&#xff0c;隐藏拖拽行列 qtableview 委托 //设置单元格委托 void setItemDelegate(QAbstractItemDelegate *delegate); QAbstractItemDelegate *it…

利用 Avalonia UI 构建 Blazor 混合应用程序

Blazor 是一个 .NET 前端框架&#xff0c;用于仅使用 .NET 技术构建 Web 应用程序。2021 年&#xff0c;Blazor 扩展到桌面端&#xff0c;推出了 Blazor Hybrid&#xff08;混合&#xff09;&#xff0c;使开发者可以在桌面平台上使用已有的技能。 Blazor 混合应用程序是传统的…