MicroZed无法使用xilffs库写入SD卡

时间:2017-03-13 19:58:27

标签: c fpga sd-card xilinx zynq

我正在使用带有Xilinx Zynq 7010的MicroZed开发板,我试图在没有任何操作系统的情况下写入SD卡,只需使用xilffs(LibXil胖文件系统)库

为了测试它,我使用的是Xilinx提供的这个xilffs_polled_example.c测试文件,但此时测试失败了:

// Write data to file.
Res = f_write(&fil, (const void*)SourceAddress, FileSize, &NumBytesWritten);
if (Res) {
    xil_printf("6: Failed to write data to file\n");
    return XST_FAILURE;
}

但是,如果我评论出测试数据验证测试,那么其他一切都是成功的:

2: Successful mount
3: Successfully created FAT volume
4: Successfully opened file with permissions
5: Successfully put pointer at beginning of file
skip write test
7:Successfully put pointer back to beginning of file
8: Successfully read data from file
skip data verification
10: Successfully closed file

我认为SD卡处于错误的模式/格式可能会有问题。我已经使用Windows 10将SD卡格式化为FAT32,如果SD卡处于只读模式,我认为此测试也会失败:

SD_File = (char *)FileName;
Res = f_open(&fil, (char *)FileName, FA_CREATE_ALWAYS | FA_WRITE | FA_READ);
if (Res) {
    xil_printf("4: Failed to open file with permissions\n");
    return XST_FAILURE;
}

以下是我的代码,除了要调试的print语句外,它与链接文件基本相同。有没有人对这个问题有什么理论?

int FfsSdPolledExample(void)
{
    FRESULT Res;
    UINT NumBytesRead;
    UINT NumBytesWritten;
    u32 BuffCnt;
    u32 FileSize = (8*1024*1024);
    //TCHAR *Path = "0:/";
    const char *Path = "0:/";

    Platform = XGetPlatform_Info();
    if (Platform == XPLAT_ZYNQ_ULTRA_MP) {
         // Since 8MB in Emulation Platform taking long time, reduced
         // file size to 8KB.
        FileSize = 8*1024;
    }

    for(BuffCnt = 0; BuffCnt < FileSize; BuffCnt++){
        SourceAddress[BuffCnt] = TEST + BuffCnt;
    }

    // Register volume work area, initialize device
    Res = f_mount(&fatfs, Path, 0);
    if (Res != FR_OK) {
        xil_printf("2: Failed to mount\n");
        return XST_FAILURE;
    }
    xil_printf("2: Successful mount\n");

    // 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("3: Failed to create FAT volume\n");
        return XST_FAILURE;
    }
    xil_printf("3: Successfully created FAT volume\n");

    // 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, (char *)FileName, FA_CREATE_ALWAYS | FA_WRITE | FA_READ);
    if (Res) {
        xil_printf("4: Failed to open file with permissions\n");
        return XST_FAILURE;
    }
    xil_printf("4: Successfully opened file with permissions\n");

    // Pointer to beginning of file
    Res = f_lseek(&fil, 0);
    if (Res) {
        xil_printf("5: Failed to put pointer at beginning of file\n");
        return XST_FAILURE;
    }
    xil_printf("5: Successfully put pointer at beginning of file\n");

    // Write data to file.
    /*
    Res = f_write(&fil, (const void*)SourceAddress, FileSize,
            &NumBytesWritten);
    if (Res) {
        xil_printf("6: Failed to write data to file\n");
        return XST_FAILURE;
    }
    xil_printf("6: Successfully written data to file\n");
    */

    //Pointer to beginning of file .
    Res = f_lseek(&fil, 0);
    if (Res) {
        xil_printf("7: Failed to put pointer back to beginning of file\n");
        return XST_FAILURE;
    }
    xil_printf("7: Successfully put pointer back to beginning of file\n");

    //Read data from file.
    Res = f_read(&fil, (void*)DestinationAddress, FileSize,
            &NumBytesRead);
    if (Res) {
        xil_printf("8: Failed to read data from file\n");
        return XST_FAILURE;
    }
    xil_printf("8: Successfully read data from file\n");

    // Data verification
    /*
    for(BuffCnt = 0; BuffCnt < FileSize; BuffCnt++){
        if(SourceAddress[BuffCnt] != DestinationAddress[BuffCnt]){
            xil_printf("9: Data verification failed\n");
            return XST_FAILURE;
        }
    }
    xil_printf("9: Data verification passed\n");
    */

    //Close file.
    Res = f_close(&fil);
    if (Res) {
        xil_printf("10: Failed to close file\n");
        return XST_FAILURE;
    }
    xil_printf("10: Successfully closed file\n");

    return XST_SUCCESS;
}

3 个答案:

答案 0 :(得分:1)

我在设计中偶然发现了同样的问题。 xilffs中的写入功能似乎已被破坏。

长话短说,问题出在diskio.c中,在连续写入期间出现了错误。卡或DMA仍然可能很忙,硬件包装器功能永远不会检查它们是免费的。

到目前为止还没有好的和稳定的解决方案,但是在disk_write()中的XSdPs_WritePolled()之前添加usleep(200)会有所帮助。

这是BSP源代码,要编辑它,您需要使用xilffs副本创建本地存储库,并将其添加到本地存储库列表(xilinx工具 - > repos),然后在本地编辑diskio.c回购并再生bsp(s)。

答案 1 :(得分:1)

问题的根源似乎是PS SD控制器,它在执行数据传输时无法正确报告其状态,并且如果过早询问状态则会进入不可预测的行为。只需等待200us即可解决问题,也许等待中断也可以这样做,但是没有经过测试。

这是sdps_v3_2中xsdps.c的补丁,应该在xilffs中调用diskio.c中的延迟。同样,您需要将xsdps lib分叉到本地repo,以使其在BSP重新生成后继续运行。请记住,它不是解决方案,而只是一种不理想的解决方法。

*** D:/A15D/Vivado/A1550_Zynq/A1550_Zynq.sdk/local_repo/drivers/sdps_v3_2/src/a Wed Jun 14 05:24:28 2017
--- D:/A15D/Vivado/A1550_Zynq/A1550_Zynq.sdk/local_repo/drivers/sdps_v3_2/src/b Fri Aug 18 10:15:01 2017
***************
*** 87,92 ****
--- 87,94 ----
  #include "sleep.h"

  /************************** Constant Definitions *****************************/
+ #define CMD_TIMEOUT             200
+ 
  #define XSDPS_CMD8_VOL_PATTERN    0x1AAU
  #define XSDPS_RESPOCR_READY   0x80000000U
  #define XSDPS_ACMD41_HCS  0x40000000U
***************
*** 1066,1071 ****
--- 1068,1074 ----
        }
    }

+   usleep(CMD_TIMEOUT);
    XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CMD_OFFSET,
            (u16)CommandReg);

我没有在zynq勘误表中找到该特定的错误,但是还有许多其他的SD控制器错误,并且所有这些错误都被标记为“将不会被修复,因为它是第三方核心”。如果你问我,这是一个奇怪的陈述,但让我们离开它。

我将进一步深入研究案例,并在此报告是否有任何值得注意的事情。

答案 2 :(得分:0)

修正了问题。

MicroZed附带的16GB Micro SD卡显然无法使用此代码。我把那张SD卡换成便宜的1GB随旧手机一样,用同样的方式格式化,现在代码可以工作了。

对于任何有问题解释的人,我都会公开提问。