热度 5
2023-12-22 17:52
615 次阅读|
0 个评论
文章目录 一、SD NAND特征 1.1 SD卡简介 1.2 SD卡Block图 二、SD卡样片 三、Zynq测试平台搭建 3.1 测试流程 3.2 SOC搭建 四、软件搭建 五、测试结果 六、总结 一、SD NAND特征 1.1 SD卡简介 雷龙的SD NAND有很多型号,在测试中使用的是CSNP4GCR01-AWM与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具有的硬件资源配置好; +;添加Timer IP核的路径,Timer IP核会在工程中给出; 点击Create Block Design创建BD工程 在创建的过程中添加Zynq 内核; 由于我们使用了板卡文件,所以内核IP是配置好的,我们只需稍作修改即可,如果是其他板卡,则需要自行配置DDR等配置; PL Fabric Clocks,将FCLK_CLK0的时钟频率修改为100Mhz 添加TimerA IP; 依次点击上方的自动设计,完成SOC搭建; 点击BD设计,并创建顶层文件 生成比特流文件; 在生成比特流文件后,将其导入SDK; Export Hardware,导出硬件;然后点击Launch SDK打开SDK进行软件设计; 四、软件搭建 在SDK中新建一个空白工程; Application project; 在新建的过程中创建一个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 = "Test.txt"; static char *SD_File; char DestinationAddress ; char txt ; char test_buffer ; 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 ; 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 { test_buffer = '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 != DestinationAddress ){ 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封装更适合无卡槽的嵌入式开发板设计,在一定的应用领域有着简化硬件设计、减小硬件面积的功能。 最后贴上测试工程的链接,还迎复现实验: https://gitee.com/gewenjie_host/sd_-nand_-zynq700_test ———————————————— 【本文转载自CSDN,作者:PPRAM】