基于Zynq FPGA的雷龙SD NAND存储芯片性能测试

文章目录

  • 前言
  • 一、SD NAND特征
    • 1.1 SD卡简介
    • 1.2 SD卡Block图
  • 二、SD卡样片
  • 三、Zynq测试平台搭建
    • 3.1 测试流程
    • 3.2 SOC搭建
  • 四、软件搭建
  • 五、测试结果
  • 六、总结

前言

随着嵌入式系统和物联网设备的快速发展,高效可靠的存储解决方案变得越来越重要。雷龙发展推出的SD NAND存储芯片,作为一种基于NAND FLASH和SD控制器集成的创新存储解决方案,以其紧凑的设计、强大的坏块管理以及优秀的纠错能力,在众多应用场景中展现出了显著的优势。为了验证这类存储芯片在实际应用中的表现,本文通过基于Xilinx Zynq 7020 FPGA平台的实验设置,对两种不同容量(4GB和32GB)的SD NAND芯片进行了详细的读写速度及稳定性测试。整个测试不仅包括了对SD卡的基本读写操作及其速度评估,还特别关注了在多次读写循环下的数据一致性和可靠性。通过这次详尽的测试,为开发者们提供有关如何有效利用SD NAND存储解决方案的第一手资料,也展示了此类存储介质在嵌入式项目中的潜在价值。

一、SD NAND特征

1.1 SD卡简介

雷龙公司推出的SD NAND存储解决方案,如CSNP4GCR01-AMW与CSNP32GCR01-AOW等型号,是专为满足现代嵌入式系统需求而设计的一种高效存储介质。这些SD NAND存储芯片结合了高性能NAND闪存与先进的SD控制器技术,能够在确保数据完整性的同时提供出色的读写速度。特别是它们具备强大的坏块管理能力和先进的纠错算法,即使在遭遇意外断电的情况下也能有效保护数据免受损失。

从技术规格来看,这些SD NAND产品兼容SD2.0标准,支持2线或4线接口配置,适用于各种不同的应用场景。它们的工作电压范围为2.7V至3.6V,这使得它们非常适合作为便携式设备或电池供电系统的理想选择。此外,这些芯片提供了两种工作模式以适应不同的性能需求:默认模式下,最大接口传输速度可达12.5MB/s;而在高速模式下,这一数值翻倍达到25MB/s,极大地提升了数据处理效率。值得注意的是,无论处于哪种模式,均需配合4条并行数据线来实现最佳性能表现。

雷龙的SD NAND存储方案还特别强调了环境适应性,其工作温度范围宽泛,从-40°C到+85°C,确保了即便是在极端条件下也能稳定运行。同时,这些芯片拥有极低的待机电流消耗(<250uA),有助于延长移动设备的电池寿命。安全性方面,除了基本的数据保护措施外,该系列产品还集成了符合SDMI最高安全标准的内容保护机制,支持通过CMD42命令实现SDNAND密码保护,增强了用户数据的安全性。另外,物理层面的写保护功能可以通过外部机械开关激活,而内部则同时提供了永久性和临时性的写保护选项,进一步增加了灵活性。

在通信协议的支持上,雷龙SD NAND芯片既支持SDIO读写也兼容SPI协议,这为开发者提供了更多样化的接入方式选择。尽管官方标称的最大读写速度可达25MB/s,但实际能达到的速度水平将取决于具体的MCU性能及所用接口类型等因素。对于那些对读写速率没有过高要求的应用场景而言,采用SPI协议往往是一个更为简便且成本效益更高的解决方案。无论是采取哪种协议,都必须严格遵循相关规范,以确保正确地建立文件系统并维持良好的数据交换质量。凭借其卓越的性能指标、丰富的功能特性以及广泛的应用潜力,雷龙SD NAND存储解决方案无疑成为了当今嵌入式领域内极具竞争力的产品之一。

1.2 SD卡Block图

image-20241107100521009

该SD卡封装为LGA-8;引脚分配与定义如下;在这里插入图片描述:

image-20241107100549001

二、SD卡样片

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

在这里插入图片描述:

image-20241107100621007

三、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次并打印报告。

image-20241107100646139

3.2 SOC搭建

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

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

image-20241107100714090

我们直接使用Zybo板卡文件创建一个工程,工程会将Zybo具有的硬件资源配置好;

image-20241107100746929

首先点击setting->IP->Repository->+;添加Timer IP核的路径,Timer IP核会在工程中给出;

image-20241107100816796

点击Create Block Design创建BD工程

Create Block Design创建BD工程

在创建的过程中添加Zynq 内核;

SD NAND添加Zynq 内核

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

双击内核IP,点击Clock Configuration->PL Fabric Clocks,将FCLK_CLK0的时钟频率修改为100Mhz

  双击内核IP,点击Clock Configuration->PL Fabric Clocks,将FCLK_CLK0的时钟频率修改为100Mhz

添加TimerA IP;

 添加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存储芯片(CSNP4GCR01-AMW与CSNP32GCR01-AOW)进行的性能测试。这些SD NAND芯片基于NAND FLASH和SD控制器实现,提供了强大的坏块管理、纠错功能以及在意外断电情况下的数据安全保障。测试过程中,使用了Xilinx Zynq 7020 FPGA作为测试平台,通过对这两种不同容量(4GB和32GB)的SD NAND芯片进行读写速度测试,发现随着读写数据量的增加,读写速度也随之提高,并且读取速度普遍高于写入速度,这与SD卡的一般特性相符。值得注意的是,CSNP32GCR01-AOW型号表现出更高的读写速度。

测试结果显示,这两种型号的SD NAND芯片在正常读写操作下的表现令人满意,而且价格合理。此外,LGA-8封装形式使得这种存储解决方案非常适合无卡槽的嵌入式开发板设计,有助于简化硬件设计并减少所需空间。然而,在尝试探索这些芯片在信息安全领域的应用时遇到了限制,因为发现芯片内置了复位或初始化机制,这阻止了研究人员提取上电时可能存在的不确定性值,因此无法进一步研究SD NAND的物理不可克隆特性。

雷龙的SD NAND存储芯片展示出了良好的性能与性价比,特别是在嵌入式开发领域中展现了其独特优势。对于那些寻求可靠且紧凑型存储解决方案的开发者而言,这是一个值得考虑的选择。

贴上测试工程的链接: https://gitee.com/gewenjie_host/sd_-nand_-zynq700_test

免费申请 SD NAND 样品,可以去官网:http://www.longsto.com/

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

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

相关文章

vscode翻译插件

vscode翻译插件 需求 &#xff1a; 在编写代码的时候&#xff0c; 打印或者定义变量的时候总是想不起来英文名称&#xff0c; 所有就开发了一款中文转换为英文的插件。 功能 1、目前支持选中中文&#xff0c;右键选择打印或者变量进行转换。 2、目前支持选中中文&#xff0…

信息安全工程师(81)网络安全测评质量管理与标准

一、网络安全测评质量管理 遵循标准和流程 网络安全测评应严格遵循国家相关标准和流程&#xff0c;确保测评工作的规范性和一致性。这些标准和流程通常包括测评方法、测评步骤、测评指标等&#xff0c;为测评工作提供明确的指导和依据。 选择合格的测评团队 测评团队应具备相关…

【C++】lambda表达式的理解与运用(C++11新特性)

&#x1f308; 个人主页&#xff1a;谁在夜里看海. &#x1f525; 个人专栏&#xff1a;《C系列》《Linux系列》 ⛰️ 天高地阔&#xff0c;欲往观之。 目录 前言 C11之前的例子 一、lambda的语法 lambda函数示例&#xff1a; 二、lambda的捕获列表 1.传值捕获 mutable修饰 2.…

K8s资源对象监控之kube-state-metrics详解(Detailed Explanation of Kube State Metrics)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…

儿童安全座椅行业全面深入分析

儿童安全座椅就是一种专为不同体重&#xff08;或年龄段&#xff09;的儿童设计&#xff0c;将孩子束缚在安全座椅内&#xff0c;能有效提高儿童乘车安全的座椅。欧洲强制性执行标准ECE R44/03的定义是&#xff1a;能够固定到机动车辆上&#xff0c;带有ISOFIX接口、LATCH接口的…

传输协议设计与牧村摆动(Makimoto‘s Wave)

有一条活鱼和一条死鱼&#xff0c;你准备怎么做&#xff0c;你会将活鱼红烧或将死鱼清蒸吗&#xff1f;好的食材只需要最简单的烹饪&#xff0c;不好的食材才需要花活儿。 我此前的文字几乎都在阐述一个观点&#xff0c;广域网就是那条死鱼&#xff0c;数据中心则是那条活鱼。…

【极限编程(XP)】

极限编程&#xff08;XP&#xff09;简介 定义与核心价值观&#xff1a;极限编程&#xff08;Extreme Programming&#xff0c;XP&#xff09;是一种轻量级、敏捷的软件开发方法。它强调团队合作、客户参与、持续测试和快速反馈等价值观&#xff0c;旨在提高软件开发的效率和质…

Autosar CP 内存抽象接口MemIf规范导读

一、MemIf规范概述 内存抽象接口(Memory Abstraction Interface,简称MemIf)是AUTOSAR架构中用于访问和管理非易失性随机存取存储器(NVRAM)的重要组成部分。以下是对MemIf的详细概述: 1. 功能和目的 MemIf的主要功能是为上层软件(如NVRAM管理器)提供统一的接口,以便…

动态规划 —— dp 问题-粉刷房子

1. 剑指offer —— 粉刷房子 题目链接&#xff1a; LCR 091. 粉刷房子 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/JEj789/description/ 2. 题目解析 根据上图可以得到costs横坐标&#xff08;行&#xff09;是房子的号数&#xff0c;红色的下标是0&…

将vscode的终端改为cygwin terminal

现在终端是默认的power shell&#xff0c;没有显示cygwin 接下来选择默认配置文件 找到cygwin的选项即可 然后提示可能不安全什么的&#xff0c;点是&#xff0c;就有了

Scala的包及其导入

//1.单个导入 //import com.sala02.A //import com.sala02.B//2.导入多个类 //import com.sala02.{A,B}//3.导入一个包下的所有类&#xff1a;包名._ //import com.sala02._//4.导入一个包中的类&#xff0c;给他改个名字 //格式&#xff1a;import 包名.{原来的名字 > 新名…

SAP B1 认证考试习题 - 解析版(三)

前一篇&#xff1a;《SAP B1 认证考试习题 - 解析版&#xff08;二&#xff09;》 题目纯享版合集&#xff1a;《SAP B1 认证考试习题 - 纯享版》 五、运费&#xff08;附加费用&#xff09; 57. 以下哪个选项能够影响库存商品的价格 A. 仅为总量级别的附加费用 B. 只为行级…

ZABBIX API获取监控服务器OS层信息

Zabbix 是一款强大的开源监控解决方案,能够通过其 API 接口自动化管理和获取监控数据。在这篇文章中,详细讲解如何通过 Zabbix API 批量获取服务器的系统名称、IP 地址及操作系统版本信息,并将数据保存到 CSV 文件中。本文适合对 Python 编程和 Zabbix 监控系统有一定基础的…

【毫米波雷达(七)】自动驾驶汽车中的精准定位——RTK定位技术

一、什么是RTK&#xff1f; RTK&#xff0c;英文全名叫做Real-time kinematic&#xff0c;也就是实时动态。这是一个简称&#xff0c;全称其实应该是RTK&#xff08;Real-time kinematic&#xff0c;实时动态&#xff09;载波相位差分技术。 二、RTK的组装 如上图所示&#x…

跨域问题以及使用vscode的LiveServer插件跨域访问

目录 现象跨域问题的定义&#xff08;文心一言&#xff09;解决办法同源部署后端代理VS Code LiveServer 现象 以下前端代码部署后&#xff0c;在网页访问时报错&#xff1a;No ‘Access-Control-Allow-Origin’ header is present on the requested resource. $.ajax({url:…

Python基础学习_01

目录 1、注释 2、数字和数学计算 3、变量 4、字符串 5、打印 6、本节总结 1、注释 • 什么是注释&#xff1f; 1&#xff09;注释就是用自然语言向代码阅读者说明代码的功能和意义 • 注释 1&#xff09;单行注释使用 # 为开头&#xff1b;并且不能换行…

C语言复习第9章 字符串/字符/内存函数

目录 一、字符串函数1.1 读取字符串gets函数原型Example 1.2 字符串拷贝strcpy函数原型模拟实现官方源码 1.3 求字符串长度strlen函数原型关于返回值size_与算术转换的一个易错点模拟实现:递归模拟实现:指针-指针模拟实现:暴力官方源码 1.4 字符串追加strcat函数原型注意自己给…

使用Matlab神经网络工具箱

综述 在大数据和人工智能时代&#xff0c;神经网络是一种最为常见的数据分析和拟合工具。本报告以常用分析软件Matlab为例&#xff0c;介绍其中神经网络工具箱使用方法。 Step 1: 打开matlab 安装matlab 2018以上版本后&#xff0c;双击图标打开。 Step 2: 打开神经网络拟合…

ffmpeg视频滤镜:组合两个视频为立体视频- framepack

视频描述 framepack 官方网址 > FFmpeg Filters Documentation 这个滤镜会将两个视频进行组合&#xff0c;有个前提是这两个视频的帧率、分别率必须一样。比如输入的是两个852x480 视频&#xff0c;输出可能是1704*480&#xff08;左右拼接&#xff09;、852*960&#xf…

Spring Security 框架篇-深入了解 Spring Security 的授权核心功能(RBAC 权限模型、自定义异常处理器、校验权限方法)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 权限系统 1.1 引入 1.2 RBAC 权限模型 1.3 数据库设计 2.0 Spring Security 核心功能-授权 2.1 思路分析 2.2 编写 SQL 语句 2.3 将用户权限进行封装 2.4 获取用户…