参考文章:
1、Zynq读写SD卡:https://blog.csdn.net/jinhua1990/article/details/84100100
2、ZYNQ开发板SD卡读写:https://blog.csdn.net/love_ljq/article/details/79117738
函数返回值检查宏:
#define check_func_return(express) do { \
int ret = 0;\
if (XST_SUCCESS != (ret=express)) \
{\
xil_printf("Func:%s:Line:%d: errcode(%d)\r\n",\
__func__,__LINE__,ret);\
return XST_FAILURE;\
} else {\
;/* xil_printf("Execute %s successfully!\r\n",#express); */\
}\
} while(0)
//用法:check_func_return(function_name1(arg));
初始化SD卡:
int SdCard_Initialize(XSdPs *InstancePtr, u16 DeviceId)
{
u32 ret = 0;
XSdPs_Config *ConfigPtr = XSdPs_LookupConfig(DeviceId);
ret = XSdPs_CfgInitialize(InstancePtr, ConfigPtr, ConfigPtr->BaseAddress);
if (ret != XST_SUCCESS) {
xil_printf("XSdPs_CfgInitialize error\r\n");
return XST_FAILURE;
}
ret = XSdPs_SdCardInitialize(InstancePtr);
if (ret != XST_SUCCESS) {
xil_printf("XSdPs_SdCardInitialize error\r\n");
return XST_FAILURE;
}
if (isSdCard_Inserted(InstancePtr))
{
xil_printf("isSdCard_Inserted!!!\r\n");
} else {
xil_printf("Sdcard is Not Inserted ...\r\n");
}
return 0;
}
检测SD卡是否已插入:
//检测SD卡是否已插入
//返回值: 1(true), 0(false)
int isSdCard_Inserted(XSdPs *InstancePtr)
{
u32 PresentStateReg = 0;
/*
* Check the present state register to make sure
* card is inserted and detected by host controller
*/
PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
XSDPS_PRES_STATE_OFFSET);
if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U) {
return 0;//false
}
return 1;//true;
}
下面的代码虽然不怎么优雅,但是关于SD卡的所有标准访问都包含了,而且尽量少的依赖全局变量,就为测试SD卡读写功能测试是否正常。SD卡IO功能测试(Sdcard_IoFunctionTest)完整源代码如下:
int Sdcard_IoFunctionTest(XSdPs *InstancePtr, u16 DeviceId/* default 0 */)
{
/*
* To test logical drive 0, Path should be "0:/"
* For logical drive 1, Path should be "1:/"
*/
TCHAR *Path = "0:/";
/*
* To test logical drive 0, FileName should be "0:/" or
* "". For logical drive 1, FileName should be "1:/"
*/
char FileName[32] = "Test.bin";
char *SD_File;
FIL fil;
FATFS fatfs;
enum {FILE_SIZE = 8*1024 };
u32 FileSize = FILE_SIZE;
UINT NumBytesWritten = 0;
UINT NumBytesRead = 0;
u8 SourceAddress[FILE_SIZE] = {0x50};
u8 DestinationAddress[FILE_SIZE] = {0x50};
u32 Res = 0;
u32 Platform = XGetPlatform_Info();
if (Platform == XPLAT_ZYNQ_ULTRA_MP) {
/*
* Since 8MB in Emulation Platform taking long time, reduced
* file size to 8KB.
*/
xil_printf("Note:%s:%d:platform is XPLAT_ZYNQ_ULTRA_MP\r\n",__FILE__,__LINE__);
;;;
}
/*
* Register volume work area, initialize device
*/
Res = f_mount(&fatfs, Path, 0);
if (Res != FR_OK) {
xil_printf("Error:%s:%d:f_mount\r\n",__FILE__,__LINE__);
return XST_FAILURE;
}
/*
* Path - Path to logical driver, 0 - FDISK format.
* 0 - Cluster size is automatically determined based on Vol size.
*/
Res = f_mkfs(Path, 0, 0);
if (Res != FR_OK) {
xil_printf("Error:%s:%d:f_mkfs\r\n",__FILE__,__LINE__);
return XST_FAILURE;
}
/*
* Open file with required permissions.
* Here - Creating new file with read/write permissions. .
* To open file with write permissions, file system should not
* be in Read Only mode.
*/
SD_File = (char *)FileName;
Res = f_open(&fil, SD_File, FA_CREATE_ALWAYS | FA_WRITE | FA_READ);
if (Res) {
xil_printf("Error:%s:%d:f_open\r\n",__FILE__,__LINE__);
return XST_FAILURE;
}
/*
* Pointer to beginning of file .
*/
Res = f_lseek(&fil, 0);
if (Res) {
xil_printf("Error:%s:%d:f_lseek\r\n",__FILE__,__LINE__);
return XST_FAILURE;
}
/*
* Write data to file.
*/
Res = f_write(&fil, (const void*)SourceAddress, FileSize,
&NumBytesWritten);
if (Res) {
xil_printf("Error:%s:%d:f_write\r\n",__FILE__,__LINE__);
return XST_FAILURE;
}
/*
* Pointer to beginning of file .
*/
Res = f_lseek(&fil, 0);
if (Res) {
xil_printf("Error:%s:%d:f_lseek\r\n",__FILE__,__LINE__);
return XST_FAILURE;
}
/*
* Read data from file.
*/
Res = f_read(&fil, (void*)DestinationAddress, FileSize,
&NumBytesRead);
if (Res) {
xil_printf("Error:%s:%d:f_read\r\n",__FILE__,__LINE__);
return XST_FAILURE;
}
/*
* Data verification
*/
for(int i = 0; i < FileSize; i++){
if(SourceAddress[i] != DestinationAddress[i]){
xil_printf("Error:%s:%d:Read and write data is inconsistent\r\n",
__FILE__,__LINE__);
return XST_FAILURE;
}
}
xil_printf("Success:Read and write data is consistent\r\n");
/*
* Close file.
*/
Res = f_close(&fil);
if (Res) {
xil_printf("Error:%s:%d:f_close\r\n",__FILE__,__LINE__);
return XST_FAILURE;
}
return 0;
}
参考文章:zynq在SDK中计算某段程序的执行时间
如何通过卡面标识区分SD卡的速度等级:https://www.cnblogs.com/pcheng/p/9156162.html
class4/class10/UHS-1/UHS-3 SD卡速度等级区别:https://www.cnblogs.com/w12n/p/6156014.html
直接可用的完整源代码片段:
void calculate_runtime(u32 Microsecond)
{
XTime tEnd,tCur;
u32 tUsed;
XTime_GetTime(&tCur);
usleep(Microsecond);
XTime_GetTime(&tEnd);
tUsed = ((tEnd-tCur)*1000000)/(COUNTS_PER_SECOND);
xil_printf("time elapsed is %d us\r\n",tUsed);
}
基于前面的SD卡IO功能测试和上面的程序执行时间统计代码片段,进行有机整合就可拼接出SD卡读写性能测试,即读写速度测试。SD卡IO性能测试(Sdcard_IoPerformanceTest)完整源代码如下:
/*****************************************************************************/
/**
*
* File system example using SD driver to write to and read from an SD card
* in polled mode. This example creates a new file on an
* SD card (which is previously formatted with FATFS), write data to the file
* and reads the same data back to verify.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int FfsSdPolledExample(void)
{
FIL fil;
FATFS fatfs;
char FileName[32] = "Test.txt";
char *SD_File;
u8 DestinationAddress[10*1024];// __attribute__ ((aligned(32)));
u8 SourceAddress[10*1024];// __attribute__ ((aligned(32)));
FRESULT Res;
UINT NumBytesRead;
UINT NumBytesWritten;
u32 BuffCnt;
enum {FF_MAX_SS = 8*1024 };
u32 FileSize = (8*1024);
XTime tEnd, tCur;
u32 tUsed;
/*
* To test logical drive 0, Path should be "0:/"
* For logical drive 1, Path should be "1:/"
*/
TCHAR *Path = "0:/";
memset(SourceAddress, 0x41, sizeof(SourceAddress));
/*
* Register volume work area, initialize device
*/
Res = f_mount(&fatfs, Path, 0);
if (Res != FR_OK) {
return XST_FAILURE;
}
/*
* Path - Path to logical driver, 0 - FDISK format.
* 0 - Cluster size is automatically determined based on Vol size.
*/
Res = f_mkfs(Path, 0, 0);
if (Res != FR_OK) {
return XST_FAILURE;
}
/*
* Open file with required permissions.
* Here - Creating new file with read/write permissions. .
* To open file with write permissions, file system should not
* be in Read Only mode.
*/
SD_File = (char *)FileName;
Res = f_open(&fil, SD_File, FA_CREATE_ALWAYS | FA_WRITE | FA_READ);
if (Res) {
return XST_FAILURE;
}
/*
* Pointer to beginning of file .
*/
Res = f_lseek(&fil, 0);
if (Res) {
return XST_FAILURE;
}
/*
* Write data to file.
*/
XTime_GetTime(&tCur);
Res = f_write(&fil, (const void*)SourceAddress, FileSize,
&NumBytesWritten);
if (Res) {
return XST_FAILURE;
}
XTime_GetTime(&tEnd);
tUsed = ((tEnd - tCur) * 1000000) / (COUNTS_PER_SECOND);
xil_printf("%s: Write Speed = %d Bytes/s\r\n",
__func__, (u32) ((16 * 1000 * 1000 * 1.0) / (tUsed * 1.0)));
/*
* Pointer to beginning of file .
*/
Res = f_lseek(&fil, 0);
if (Res) {
return XST_FAILURE;
}
/*
* Read data from file.
*/
XTime_GetTime(&tCur);
Res = f_read(&fil, (void*)DestinationAddress, FileSize,
&NumBytesRead);
if (Res) {
return XST_FAILURE;
}
XTime_GetTime(&tEnd);
tUsed = ((tEnd - tCur) * 1000000) / (COUNTS_PER_SECOND);
xil_printf("%s: Read Speed = %d Bytes/s\r\n",
__func__, (u32) ((16 * 1000 * 1000 * 1.0) / (tUsed * 1.0)));
/*
* Data verification
*/
for(BuffCnt = 0; BuffCnt < FileSize; BuffCnt++){
if(SourceAddress[BuffCnt] != DestinationAddress[BuffCnt]){
xil_printf("Error:%d:SourceAddress[BuffCnt] != DestinationAddress[BuffCnt]\r\n",__LINE__);
return XST_FAILURE;
}
}
xil_printf("DestinationAddress = ");
for (int i=0; i<16; i++) {
xil_printf("%02x ", DestinationAddress[i]);
}
xil_printf("\r\n");
/*
* Close file.
*/
Res = f_close(&fil);
if (Res) {
return XST_FAILURE;
}
return XST_SUCCESS;
}