基于Zynq FPGA对雷龙SD NAND的测试

一、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都需要符合相关的协议规范,才能建立相应的文件系统;


二、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中定义;

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的物理不可克隆特性,所以这方面的测试无法进行;

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

最后贴上测试工程的链接,还迎复现实验: 代码链接。

雷龙官网:地址

相关推荐
玄奕子14 天前
通过Zynq FPGA对雷龙SD NAND进行测试
嵌入式·fpga·flash·sd nand·嵌入式驱动·雷龙
我想学LINUX1 个月前
基于Zynq FPGA对雷龙SD NAND的测试
嵌入式硬件·学习·fpga开发·sd nand·雷龙开发
不是笨小孩i1 个月前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发·sd nand·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
DS小龙哥2 个月前
基于Zynq FPGA的雷龙SD NAND存储芯片性能测试
fpga开发·sd nand·雷龙·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
码农阿豪2 个月前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发·sd nand·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
MK米客方德5 个月前
TF卡(SD NAND)参考设计和使用提示
嵌入式硬件·flash·sd nand·layout设计
EmotionFlying1 年前
ESP32应用教程(2)— SD NAND(记录飞控LOG)
esp32·sd nand·贴片式sd卡