当前位置: 首页 > article >正文

通过Zynq FPGA对雷龙SD NAND进行测试

目录

引言:

一、SD NAND特征

1.1 SD卡简介

1.2 SD卡Block图

二、SD卡样片

三、Zynq测试平台搭建

3.1 测试流程

3.2 SOC搭建

四、软件搭建

五、测试结果

六、总结


引言:

在嵌入式系统开发中,SD NAND因其高可靠性、低功耗和小封装等优势,被广泛应用于数据存储和传输场景。本文详细介绍了基于Zynq-7020 FPGA平台对CSNP4GCR01-AMW和CSNP32GCR01-AOW两种型号SD NAND芯片的读写性能测试过程及结果。测试包括SD卡的初始化、FATFS文件系统的搭建、数据读写速度测量及一致性验证,并分析了不同容量SD NAND的性能差异。本测试使用LGA-8封装芯片,并通过转接板兼容传统SD卡接口,为无卡槽嵌入式设计提供了灵活选择。测试结果表明,这些芯片在嵌入式存储领域具有较高的应用价值,同时为后续项目提供了可靠的数据支持和性能参考。

SD NAND-雷龙发展有限公司icon-default.png?t=O83Ahttp://www.longsto.com/product/31.html

一、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卡封装为LGA-8;引脚分配与定义如下;在这里插入图片描述:

二、SD卡样片

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

在这里插入图片描述:

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

3.2 SOC搭建

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

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

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

 

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

点击Create Block Design创建BD工程

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

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

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

添加TimerA IP;

依次点击上方的自动设计,完成SOC搭建;

点击BD设计,并创建顶层文件

生成比特流文件;

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

点击Export->Export Hardware,导出硬件;然后点击Launch SDK打开SDK进行软件设计;

四、软件搭建

在SDK中新建一个空白工程;

点击file -> new -> Application project;

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

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

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

#include “xparameters.h” /* SDK 生成的参数 */

#include “xsdps.h” /* SD 设备驱动程序 */

#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) {

返回 XST_FAILURE;

        }





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

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

xil_printf(“%dno”,BuffCnt);

返回 XST_FAILURE;

            }

        }

xil_printf(“测试编号:%d 数据检查正确!\n”,test_time+1);

test_time++;

如果(test_time==100)

        {

sprintf(txt,“总写入量:%.2f KB,花费时间:%.2f ms,写入速度:%.2f MB/s\n”,PACK_LEN*100/1024.0,w_t/100.0/1000.0,wsum/100/1024/1024);

xil_printf(txt);

sprintf(txt,“总读取量:%.2f KB,花费时间:%.2f ms,读取速度:%.2f MB/s\n”,PACK_LEN*100/1024.0,r_t/100.0/1000.0,rsum/100/1024/1024);

xil_printf(txt);

分辨率 = f_close(&fil);

if (Res) {

返回 XST_FAILURE;

            }

返回 0;

        }

    }



}



int main(void) (无效)

{

TimerA0_init();



SDCard_test();

xil_printf(“完成”);

返回 0;

}

五、测试结果

经测试,两种型号的芯片读写速度如下图表所示。

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

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

六、总结

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

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


http://www.kler.cn/a/429694.html

相关文章:

  • 【2024年华为OD机试】(C卷,100分)- 分割均衡字符串 (Java JS PythonC/C++)
  • ORACLE-表空间和分区控制
  • Qi认证怎么办理?
  • E10.【C语言】练习:编写一个猜数字游戏
  • 银河麒麟服务器操作系统桌面任务栏网络图标消失问题
  • Kutools for Excel 简体中文版 - 官方正版授权
  • 黑马商城docker部署部分MySQL拉取超时解决方法
  • 前端学习纪要
  • java八股-流量封控系统
  • Leetcode 每日一题 1.两数之和
  • Linux图形化工具推荐
  • 【sgUploadImage】自定义组件:基于elementUI的el-upload封装的上传图片、相片组件,适用于上传缩略图、文章封面
  • 【Linux】08 -- 重定向命令及管道命令
  • mac下flutter开发环境的配置
  • CGAL自相交修复测试
  • 使用Python3 连接操作 OceanBase数据库
  • 碰撞算法8 --直线与圆的碰撞
  • UART+DDR3+HDMI联合图像存储与显示系统
  • git 过滤检出包含windows平台不兼容文件
  • FSC认证是什么?FSC认证费用
  • Elasticsearch一分钟
  • 如何借助 LLM Gateway (LLM网关)同时接入多款 AI 大模型?
  • 2024年深圳杯数学建模C题编译器版本的识别问题解题全过程文档及程序
  • C语言 字符数组/多维数组/函数/作用域
  • 【MySQL 进阶之路】存储引擎和SQL优化技巧分析
  • 力扣刷题TOP101: 24.BM30 二叉搜索树与双向链表