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

基于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控制器设计,支持强大的坏块管理和纠错功能,并能在意外断电的情况下确保数据安全。

其主要特点包括:

  • 接口支持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最高安全标准;
  • 支持SD NAND密码保护(CMD42 - LOCK_UNLOCK);
  • 内置写保护功能(永久和临时);
  • 提供机械开关的写保护功能;
  • 提供应用程序特定命令;
  • 支持舒适擦除机制。

该SD卡支持SDIO和SPI协议读写,最高读写速度可达25MB/s。实际的读写速度会根据MCU和接口情况进行调整。通常在简单的嵌入式系统中,若对读写速度要求不高,会选择使用SPI协议。但无论使用SDIO还是SPI,都需要符合相关协议规范,才能成功搭建文件系统。

1.2 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 测试流程

本次测试针对4GB和32GB两种容量的SD卡,在Zynq FPGA上搭建了SD卡读写回路,旨在测试SD卡的读写速度并验证读写一致性。

测试步骤如下:

  1. 初始化SD卡并建立FATFS文件系统;
  2. 进入测试程序,首先写入一定大小的文件,然后测量写入时间;
  3. 读取文件并测量读取时间;
  4. 比较读取数据和写入数据,确保数据一致;
  5. 通过写入时间和读取时间计算写入速度和读取速度。

测试过程将重复进行100次,最终输出测试报告。

(此处插入图片:Zynq FPGA上搭建的SD卡读写回路)

3.2 SOC搭建

硬件搭建框图如下,在本系统中我们使用了PS端的SDIO接口来驱动SD NAND芯片,并通过UART与PC进行数据交互。

PL端硬件搭建非常简单,仅使用了一个Timer定时器来测量时间。

(此处插入图片:SD NAND(SD卡)PL端的硬件搭建)

使用Zybo板卡文件创建工程,该文件会自动配置板卡中的硬件资源,若使用其他板卡,则需要手动配置DDR等硬件资源。

在这里插入图片描述

创建工程的步骤如下:

  1. 点击Setting -> IP -> Repository -> +,添加Timer IP核的路径;

在这里插入图片描述

  1. 创建Block Design(BD)工程;

在这里插入图片描述

  1. 配置Zynq内核,修改时钟配置为100MHz;

在这里插入图片描述

在这里插入图片描述

  1. 添加TimerA IP;

在这里插入图片描述

  1. 自动生成设计并完成SOC搭建。

在这里插入图片描述

完成硬件搭建后,生成比特流文件,并将其导入到SDK中。
在这里插入图片描述
在这里插入图片描述


四、软件搭建

在SDK中创建一个空白工程,并在其中编写测试程序。在每次读写操作开始之前,通过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;
}

测试过程中,我们通过写入和读取文件测得读写时间,计算出实际的读写速度,并将结果与预期值进行对比。


五、测试结果

经过测试,4GB和32GB两种型号的SD NAND芯片的读写速度如下:

  • 写入速度:随着数据量的增加,写入速度也会增加;
  • 读取速度:读取速度通常会高于写入速度,这符合SD卡的常规特性。

CSNP32GCR01-AOW型号的SD NAND芯片相较于CSNP4GCR01-AMW,具有更高的读写速度。

(此处插入图表:SD NAND的读写速度数据)

在这里插入图片描述


六、总结

虽然原计划尝试将这些样片用于信息安全领域,但由于芯片内部似乎内置了复位或初始化功能,导致无法提取上电时的不确定值,因此未能进行SD NAND的物理不可克隆特性测试。

然而,关于芯片正常读写功能的测试结果令人满意,且芯片的价格具有竞争力。LGA-8封装形式特别适合用于没有卡槽的嵌入式开发板设计,能够有效简化硬件设计和减小硬件面积。

测试工程的链接可见:测试工程链接。


官网参考:雷龙官网


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

相关文章:

  • 【MySQL】数据库知识突破:数据类型全解析与详解
  • 域名服务系统DNS (Domain Name System)
  • linux rocky 9.4部署和管理docker harbor私有源
  • Electron 项目中杀掉进程的不同方式
  • 自监督学习:机器学习的未来新方向
  • 萤石设备视频接入平台EasyCVR海康私有化视频平台监控硬盘和普通硬盘有何区别?
  • Unet++改进9:添加LSKBlock||动态调整其大空间感受场
  • LeetCode 876.链表的中间结点
  • keep-alive的tab栏内容缓存
  • 共享汽车管理:SpringBoot框架的创新应用
  • vue2 - el-table表格设置动态修改表头
  • 底层视角看C语言
  • EasyExcel的AbstractColumnWidthStyleStrategy注入CellStyle不生效
  • 网页版五子棋—— WebSocket 协议
  • IntelliJ IDEA 中创建目录时 `.` 和 `/` 的区别
  • 【Hadoop和Hbase集群配置】3台虚拟机、jdk+hadoop+hbase下载和安装、环境配置和集群测试
  • go中的类型断言详解
  • 学习笔记:黑马程序员JavaWeb开发教程(2024.11.9)
  • 使用成熟的框架做量化剪枝蒸馏
  • 机器学习系列----梯度下降算法
  • MVDR:最小方差无失真响应技术解析
  • 通过 Nacos 服务发现进行服务调用时的 500 错误排查与解决
  • C++类和对象 (下)
  • Linux数据管理初探
  • PG COPY 与 INSERT方式导入数据时, 表默认值表现的不同
  • 使用k8s RBAC和ValidatingAdmissionPolicy 配合来校验用户权限