最近我正在进行一个Zynq项目,我使用了Xilinx SDK自带的系统库函数来读取SD卡中的配置信息。然而,一直读取异常。
我进行了一系列的调试和检查,包括确认PS部分的代码正确性以及Xilffs的配置是否正确,但是问题仍然没有解决。最后,只能亲自检查同事开发的PL部分代码,希望能找到问题的原因。
首先,分享一下本项目中导致读取异常的原因。
原因:勾选了“CD”项,这一项是否勾选要结合原理图设计,SD卡插槽上的CD引脚是否正确连接到Zynq芯片的MIO引脚。(如下图)本项目MIO47引脚用作USB功能,并未接到SD的CD引脚上。
原理图:
通过查阅资料,总结了几个需要注意的地方:
1、CD (Card Detect)引脚是用于检测SD卡是否插入,设计时候需要注意:
(1)引脚连接:确保CD MIO47引脚正确连接到SD卡插槽的检测引脚上。
(2)引脚功能配置:在PL或者PS设计中,需要将CD MIO47引脚配置为GPIO输入模式,并设置为上拉电阻或者禁用上拉电阻,以此能够正确读取引脚状态。
(3)软件配置:如果勾选了CD项,在PS驱动程序中,需要根据GPIO来判断SD卡是否插入。
2、WP(Write Protect)引脚是否勾选也十分关键,WP功能是检测和设置SD卡是否处于写保护状态。当WP引脚连接到GPIO引脚,并设置为高电平时,SD卡会被设置为写保护状态,即无法对其进行写入操作。如果需要防止误写入,可以通过设置WP引脚,限制对SD卡的写入权限,防止意外的数据修改或删除。
3、Power引脚是SD卡电源引脚,用于提供电源给SD卡。
PS端驱动程序:
1、创建工程,勾选通用FAT文件系统库,即“xilffs”。
2,将“use_lfn”项改为“true”,默认是“false”。use_lfn是是否支持长文件名(Long File Name,LFN)。长文件名是指文件名超过8个字符(不包括扩展名)的文件名。
当use_lfn设置为true时,文件系统可以存储和读取超过8个字符的文件名,文件名也可以使用空格、特殊字符和中文等非传统字符。
代码如下:
#define SD_DATA_LENGTH (256)
FATFS SD_Dev; // File System instance
char *SD_Path = "0:/"; // string pointer to the logical drive number
char FileName[32] = "config.txt"; // name of the log
char WR_Buf[SD_DATA_LENGTH] __attribute__ ((aligned(32))); // Buffer should be word aligned (multiple of 4)
char RD_Buf[SD_DATA_LENGTH] __attribute__ ((aligned(32))); // Buffer should be word aligned (multiple of 4)
#include "ff.h" // 引入FatFs库
int SD_init()
{
FRESULT result;
// 挂载SD卡设备
result = f_mount(&SD_Dev, SD_Path, 0);
if (result != 0) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
int SD_read(char *FileName, char *DestinationAddress, unsigned int ByteLength)
{
FIL file;
FRESULT result;
UINT BytesRd;
// 打开文件
result = f_open(&file, FileName, FA_READ);
if (result) {
return XST_FAILURE;
}
// 读取文件内容
result = f_lseek(&file, 0);
if (result) {
return XST_FAILURE;
}
result = f_read(&file, (void*)DestinationAddress, ByteLength, &BytesRd);
if (result) {
return XST_FAILURE;
}
// 关闭文件
result = f_close(&file);
if (result) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
int SD_write(char *FileName, char *SourceAddress, unsigned int ByteLength)
{
FIL file;
FRESULT result;
UINT BytesWr;
// 创建文件并打开
result = f_open(&file, FileName, FA_CREATE_ALWAYS | FA_WRITE);
if (result) {
return XST_FAILURE;
}
// 写入文件内容
result = f_lseek(&file, 0);
if (result) {
return XST_FAILURE;
}
result = f_write(&file, (void*)SourceAddress, ByteLength, &BytesWr);
if (result) {
return XST_FAILURE;
}
// 关闭文件
result = f_close(&file);
if (result) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
int main()
{
int ret;
/*SD card init*/
SD_init();
ret = SD_write(FileName, WR_Buf, SD_DATA_LENGTH);
if (ret == XST_SUCCESS)
{
xil_printf("SD CARD written Successfully\r\n");
}
/*read sd data*/
ret = SD_read(FileName, RD_Buf, SD_DATA_LENGTH);
if(ret == XST_SUCCESS)
{
xil_printf("Successfully read the configuration file from the SD card.\n");
}
else
{
xil_printf("Error read SD card configuration file.\n");
}
}
PS:查阅资料,总结了xilffs配置中主要标志位使用和设置方法:
-
enable_exfat:启用exFAT文件系统。exFAT是一种用于大容量存储设备的文件系统,支持文件大小超过4GB。如需要使用exFAT文件系统,将这个标志位设置为1。
-
enable_multi_partition:启用多分区。如需要在设备上创建多个分区,可以将这个标志位设置为1。
-
fs_interface:指定文件系统接口。可选的值有XILFFS_IF_PS7_SD_0、XILFFS_IF_PS7_SD_1、XILFFS_IF_PS7_SD_2,分别对应不同的SD卡接口。你需要根据你的系统硬件配置选择适当的接口。
-
num_logical_vol:指定逻辑卷数量。对于支持多分区的设备,你可以设置这个值来指定分区数量。
-
read_only:设置文件系统为只读模式。如果你需要保护文件系统免受写入操作的影响,可以将这个标志位设置为1。
-
set_fs_rpath:设置文件系统的根路径。你可以指定一个字符串作为文件系统的根目录,例如"/mnt/"。
-
use_lfn:启用长文件名支持。如果你需要支持长文件名(超过8个字符),可以将这个标志位设置为1。
-
use_mkfs:启用格式化文件系统的功能。如果你希望在初始化文件系统时进行格式化操作,可以将这个标志位设置为1。
-
use_strfunc:启用字符串处理函数。如果你需要在文件系统中使用字符串处理函数,可以将这个标志位设置为1。
-
word_access:启用字节访问模式。默认情况下,文件系统使用字节级别的访问模式。如果你需要使用字级别的访问模式,可以将这个标志位设置为1。
-
ramfs_size:指定RAM文件系统的大小。RAM文件系统是一个基于内存的虚拟文件系统,用于存储临时文件。你可以设置这个值来指定RAM文件系统的大小。
REF:
VIVADO 7.ZYNQ读取SD卡_馍加馒头的博客-CSDN博客