ZYNQ开发板SD卡读写

时间:2021-08-20 04:00:13

  刚学习了一些关于ZYNQ开发板中SD卡读取的内容,想要在这里进行一下总结。
  这篇博客主要参考了以下一些博客、网页
  [1]. https://forums.xilinx.com/t5/Embedded-Development-Tools/SDK-2015-2-problem-with-xilffs-3-0/td-p/653278
  [2].https://github.com/Xilinx/embeddedsw/tree/master/lib/sw_services/xilffs
  [3].http://blog.csdn.net/husipeng86/article/details/52262070
  [4].http://blog.csdn.net/mcupro/article/details/73694460
  [5].http://elm-chan.org/fsw/ff/00index_e.html

  ZYNQ嘛,肯定是要进行PS端的配置,配置PS端的时候,其实就是配置SD卡和UART,这些配置参数就跟之前的实验一样,要注意IO Type以及Speed的设置,这里就不着重强调了,下图是我配置完的一个状态,很简单。


ZYNQ开发板SD卡读写

  导出Hardware,然后Launch SDK,然后新建一个HelloWorld的Application。Xilinx Tools->Board Support Package Setting,双击bsp,勾选xliffs库,这个库是用于SD卡读写的,目前(2018年1月21日)已经更新到版本v3.7了,我目前用的是3.1版本,参考文献【2】是这个库的GitHub,参考文献【5】是这个库的文档说明。
ZYNQ开发板SD卡读写

  以下是所有的代码,这个代码主要参考文献【4】

#include "platform.h"
#include "xparameters.h"
#include "xil_printf.h"
#include "ff.h"
#include "xdevcfg.h"

static FATFS fatfs;

int SD_Init()
{
FRESULT rc;
rc = f_mount(&fatfs,"",0);
if(rc)
{
xil_printf("ERROR: f_mount returned %d\r\n",rc);
return XST_FAILURE;
}
return XST_SUCCESS;
}

int SD_Transfer_read(char *FileName,u32 DestinationAddress,u32 ByteLength)
{
FIL fil;
FRESULT rc;
UINT br;

rc=f_open(&fil,FileName,FA_READ);
if(rc)
{
xil_printf("ERROR:f_open returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_lseek(&fil,0);
if(rc)
{
xil_printf("ERROR:f_open returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_read(&fil,(void*)DestinationAddress,ByteLength,&br);
if(rc)
{
xil_printf("ERROR:f_open returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_close(&fil);
if(rc)
{
xil_printf("ERROR:f_open returned %d\r\n",rc);
return XST_FAILURE;
}
return XST_SUCCESS;
}

int SD_Transfer_write(char *FileName,u32 SourceAddress,u32 ByteLength)
{
FIL fil;
FRESULT rc;
UINT bw;

rc = f_open(&fil,FileName,FA_CREATE_ALWAYS | FA_WRITE);
if(rc)
{
xil_printf("ERROR : f_open returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_lseek(&fil, 0);
if(rc)
{
xil_printf("ERROR : f_lseek returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_write(&fil,(void*) SourceAddress,ByteLength,&bw);
if(rc)
{
xil_printf("ERROR : f_write returned %d\r\n", rc);
return XST_FAILURE;
}
rc = f_close(&fil);
if(rc){
xil_printf("ERROR : f_close returned %d\r\n",rc);
return XST_FAILURE;
}
return XST_SUCCESS;
}

#define FILE "test.txt"

int main()
{
init_platform();
int rc;

const char src_str[] = "hsp test sd card write and read!";
u32 len = strlen(src_str);

rc = SD_Init();
if(XST_SUCCESS != rc)
{
xil_printf("fail to open SD Card~\n\r");
}
else
{
xil_printf("success to open SD Card~\n\r");
}

rc = SD_Transfer_write(FILE,(u32)src_str,(len/256+1)*256);
xil_printf("%d",(len/256+1)*256);
if(XST_SUCCESS != rc)
{
xil_printf("fail to write SD Card~\n\r");
}
else
{
xil_printf("success to write SD Card~\n\r");
}
char dest_str[33];
rc = SD_Transfer_read(FILE,(u32)dest_str,(len+1));
if(XST_SUCCESS != rc)
{
xil_printf("fail to read SD Card~\n\r");
}
else
{
xil_printf("success to read SD Card~\n\r");
}
xil_printf("%s\r\n",dest_str);
printf("SD Card Write and Read Success~");
cleanup_platform();
return 0;
}

  在f_write这个函数后面,原作者有那么一句注释//当直接指定len时没有写出,需要指定较大的长度才会写出,原因未知,于是原作者直接将len+1000,这样呢,问题貌似解决了,但是我比较想知道这个原因,我自己也试了一下,确实写入一小串字符串并写不进去。我查看了其他的文档博客,然后把源代码中的ByteWidth改为了(len/256+1)*256,也就是取了256的整数倍,这样呢,原本想要写入的数据都写入进去了,就是稍微浪费了一点资源。至于为什么写入的数据必须大于某个阈值,或者是为什么必须是256的整数倍这一点呢,我暂时还没找到原因以及更好的解决方案。
  在这个库中呢,有一个函数f_printf,但是当我想要用这个函数的时候,却提示 undefined reference to `f_printf’ ,感觉非常奇怪,并不知道问题出在哪里,在.h和.c文件中都有相关定义声明。参考资料【1】似乎是关于这个问题的解决方案,但是我自己试了发现并没有解决这个问题。
  这里还有一点要注意的就是SD的磁盘格式,这个库支持FAT16和FAT32,如果是NTFS估计应该识别不了,我用的是FAT32磁盘格式。
  既然目前这个库已经更新到了v3.7了,那以上的一些问题是否解决了呢,等我试一下,试完了之后跟大家讲一下。