从vivado 2015.2迁移到2016.4后初始化和使用SD卡不起作用

时间:2017-03-13 10:06:49

标签: c sd-card xilinx vivado

---------------编辑:附加说明---------------------------- -------------

我们只尝试过迁移到Vivado 2016.1。使用该版本,SD卡正在使用新功能,即使它以某种方式破坏了音频编解码器。这非常有趣,因为我们查找了2015.2到2016.4的每个补丁说明,唯一提到的是他们为sd卡I / O添加了额外的数据类型,在下一个版本中再次取出。

---------------- END EDIT ----------------------------- ---------------------------

我们刚刚将我们的机器人项目从vivado 2015.2迁移到2016.4,升级后,当fpga(zynq 7020)启动时,sd映像闪烁,但处理器代码将不会被执行。经过一些调试后我们发现,我们必须使用新的FSBL和BSP创建一个新的SDK项目,并将源文件包含在一个新的空应用程序中。在此之后程序陷入循环,所以我们不得不进一步调试。然后我们发现我们必须用旧的SD卡功能(TRM UG585中推荐的那些)替换我们的实际SD卡功能。

新SD功能:

        void readBlock(unsigned char sd_id, unsigned int sector, unsigned int* buf){
            unsigned int baseaddress = sd_id == 0 ? SD0_BASEADDRESS : SD1_BASEADDRESS;                          //        Choose baseaddress based on the desired SD-slot
                                                                                                                //        START
            TO_REG(baseaddress + SD_BLOCK_SIZE_REG_OFFSET) = SD_BLOCKCOUNT1_BLOCKSIZE512;                       // (1)    Set Block Size Reg -> 512 Bytes, (2) Set Block Count Reg -> 1 Block
            TO_REG(baseaddress + SD_ARGUMENT_REG_OFFSET) = sector;                                              // (3)    Set Argument Reg -> Readaddress
            TO_REG(baseaddress + SD_TRANSFER_MODE_COMMAND_REG_OFFSET) = SD_SINGLEBLOCK_READ;                    // (4/5)  Set Transfer Mode / Command Reg -> CMD17, Normal, Data Present, Enable Index-Check, Enable CRC-Check, Response length 48, Single Block, Read, Disable Auto CMD12, Disable Block Count, Disable DMA

                while(!SD_CMD_COMPLETE_INTERRUPT(baseaddress));                                                     // (6)    Wait for Command Complete Interrupt
                TO_REG(baseaddress + SD_INTERRUPT_STATUS_REG_OFFSET) = SD_INTERRUPT_STATUS_CMD_COMPLETE_MASK;       // (7)    Clear Command Complete Status
        // (8)    Get Response Data -> ignored, maybe checked for errors and retry                                                                                                  
        // (9)    Write or Read -> Read

        while(!SD_BUFFER_READ_RDY_INTERRUPT(baseaddress));                                                  // (10-R) Wait for Buffer Read Ready Interrupt
        TO_REG(baseaddress + SD_INTERRUPT_STATUS_REG_OFFSET) = SD_INTERRUPT_STATUS_BUFFER_READ_RDY_MASK;    // (11-R) Clear Buffer Read Ready Status

        for(unsigned char i = 0; i< 128; i++)                                                               // (12-R) Get Block Data
            buf[i] = TO_REG(baseaddress + SD_BUFFER_DATA_PORT_REG_OFFSET);
    // (13-R) More Blocks? -> No
                                                                                                            // (14)   Single/Multi/Infinite Block Transfer? -> Single

    while(!SD_TRANSFER_COMPLETE_INTERRUPT(baseaddress));                                                // (15)   Wait for Transfer Complete Interrupt
        TO_REG(baseaddress + SD_INTERRUPT_STATUS_REG_OFFSET) = SD_INTERRUPT_STATUS_TRANSFER_COMPLETE_MASK;  // (16)   Clear Transfer Complete Status
                                                                                                            //        END
    }

    void writeBlock(unsigned char sd_id, unsigned int sector, unsigned int* buf){
        unsigned int baseaddress = sd_id == 0 ? SD0_BASEADDRESS : SD1_BASEADDRESS;                          //        Choose baseaddress based on the desired SD-slot
                                                                                                            //        START
        TO_REG(baseaddress + SD_BLOCK_SIZE_REG_OFFSET) = SD_BLOCKCOUNT1_BLOCKSIZE512;                       // (1)    Set Block Size Reg -> 512 Bytes, (2) Set Block Count Reg -> 1 Block
        TO_REG(baseaddress + SD_ARGUMENT_REG_OFFSET) = sector;                                              // (3)    Set Argument Reg -> Readaddress
        TO_REG(baseaddress + SD_TRANSFER_MODE_COMMAND_REG_OFFSET) = SD_SINGLEBLOCK_WRITE;                   // (4/5)  Set Transfer Mode / Command Reg -> CMD24, Normal, Data Present, Enable Index-Check, Enable CRC-Check, Response length 48, Single Block, Write, Disable Auto CMD12, Disable Block Count, Disable DMA

        while(!SD_CMD_COMPLETE_INTERRUPT(baseaddress));                                                     // (6)    Wait for Command Complete Interrupt
        TO_REG(baseaddress + SD_INTERRUPT_STATUS_REG_OFFSET) = SD_INTERRUPT_STATUS_CMD_COMPLETE_MASK;       // (7)    Clear Command Complete 

    Status
        // (8)    Get Response Data -> ignored, maybe checked for errors and retry                                                                                                          
    // (9)    Write or Read -> Write

        while(!SD_BUFFER_WRITE_RDY_INTERRUPT(baseaddress));                                                 // (10-W) Wait for Buffer Write Ready Interrupt
        TO_REG(baseaddress + SD_INTERRUPT_STATUS_REG_OFFSET) = SD_INTERRUPT_STATUS_BUFFER_WRITE_RDY_MASK;   // (11-W) Clear Buffer Write Ready Status

        for(unsigned char i = 0; i< 128; i++)                                                               // (12-W) Set Block Data
            TO_REG(baseaddress + SD_BUFFER_DATA_PORT_REG_OFFSET) = buf[i];
    // (13-W) More Blocks? -> No
                                                                                                            // (14)   Single/Multi/Infinite Block Transfer? -> Single

    while(!SD_TRANSFER_COMPLETE_INTERRUPT(baseaddress));                                                // (15)   Wait for Transfer Complete Interrupt
        TO_REG(baseaddress + SD_INTERRUPT_STATUS_REG_OFFSET) = SD_INTERRUPT_STATUS_TRANSFER_COMPLETE_MASK;  // (16)   Clear Transfer Complete Status
                                                                                                            //        END
    }

旧SD功能:

DRESULT readBlock(unsigned char sd_id, unsigned long sector, unsigned char* buff){

    unsigned int count = 1;

        if(sd_id > 1) return RES_ERROR; //only id = 0 or id = 1 is valid

        s32 Status;
        DWORD LocSector = sector;

        /* Convert LBA to byte address if needed */
        if ((SdInstance[sd_id].HCS) == 0U) {
            LocSector *= (DWORD)XSDPS_BLK_SIZE_512_MASK;
        }

        Status = XSdPs_ReadPolled(&SdInstance[sd_id], (u32)LocSector, count,(unsigned char *) buff);
        if (Status != XST_SUCCESS) {
            return RES_ERROR;
        }

        return RES_OK;
}


DRESULT writeBlock(unsigned char sd_id, unsigned long sector, unsigned char* buff){

        unsigned int count = 1;
        if(sd_id > 1) return RES_ERROR; //only id = 0 or id = 1 is valid

        s32 Status;
        DWORD LocSector = sector;

        /* Convert LBA to byte address if needed */
        if ((SdInstance[sd_id].HCS) == 0U) {
            LocSector *= (DWORD)XSDPS_BLK_SIZE_512_MASK;
        }

        Status  = XSdPs_WritePolled(&SdInstance[sd_id], (u32)LocSector, count,buff);
        if (Status != XST_SUCCESS) {
            return RES_ERROR;
        }

        return RES_OK;
    }

这解决了处理器代码的问题,但我们仍然无法在SD卡上初始化或执行IO操作。此外,我们发现在初始化SD时,函数getBusWidth(bsp)在尝试调用XSdPs_CmdTransfer() - &gt;时会失效。 XSdPs_ReadReg()。当我们尝试使用旧功能在SD卡上执行IO操作时,情况似乎也是如此。

SD初始化功能:

unsigned char initSD(unsigned char sd_id){

    if(sd_id > 1) return 0xFF; //only id = 0 or id = 1 is valid

    DSTATUS s = 0;
    s32 Status;
    u8 SCR[8] = {0U};
    u8 ReadBuff[64] = {0U};

    XSdPs_Config *SdConfig = NULL;

    /*
     * Initialize the host controller
     */
    SdConfig = &XSdPs_ConfigTable[sd_id];

    Status = XSdPs_CfgInitialize(&SdInstance[sd_id], SdConfig, SdConfig->BaseAddress);
    if (Status != XST_SUCCESS) {
        s |= STA_NOINIT;
        return s;
    }

    Status = XSdPs_SdCardInitialize(&SdInstance[sd_id]);
    if (Status != XST_SUCCESS) {
        s |= STA_NOINIT;
        return s;
    }

    Status = XSdPs_Change_ClkFreq(&SdInstance[sd_id], SD_CLK_25_MHZ);
    if (Status != XST_SUCCESS) {
        s |= STA_NOINIT;
        return s;
    }

    Status = XSdPs_Select_Card(&SdInstance[sd_id]);
    if (Status != XST_SUCCESS) {
        s |= STA_NOINIT;
        return s;
    }

    Status = XSdPs_Get_BusWidth(&SdInstance[sd_id], SCR);
    if (Status != XST_SUCCESS) {
        s |= STA_NOINIT;
        return s;
    }

    Status = XSdPs_Get_BusSpeed(&SdInstance[sd_id], ReadBuff);
    if (Status != XST_SUCCESS) {
        s |= STA_NOINIT;
        return s;
    }

    if((ReadBuff[13] & HIGH_SPEED_SUPPORT) != 0U){
        Status = XSdPs_Change_BusSpeed(&SdInstance[sd_id]);
        if (Status != XST_SUCCESS) {
            s |= STA_NOINIT;
            return s;
        }
    }

    Status = XSdPs_Pullup(&SdInstance[sd_id]);
    if (Status != XST_SUCCESS) {
        s |= STA_NOINIT;
        return s;
    }

    if ((SCR[1] & WIDTH_4_BIT_SUPPORT) != 0U) {
        Status = XSdPs_Change_BusWidth(&SdInstance[sd_id]);
        if (Status != XST_SUCCESS) {
            s |= STA_NOINIT;
            return s;
        }
    }

    Status = XSdPs_SetBlkSize(&SdInstance[sd_id], (u16)XSDPS_BLK_SIZE_512_MASK);
    if (Status != XST_SUCCESS) {
        s |= STA_NOINIT;
        return s;
    }

在对我们的问题进行了这么简短的描述之后;),现在回答我的问题。你们中的任何人遇到过类似的问题并且知道解决方法或者能指出我们可以找到解决方案的方向吗?

提前致谢:)。

Delet0r

2 个答案:

答案 0 :(得分:0)

我们也尝试过Vivado 2016.3,它适用于SD卡,即使我们不知道为什么。我们还没有检查其他一切是否有效,但现在似乎是一种解决方法。

希望它在2017年修复。

答案 1 :(得分:0)

之前它有效,这意味着您的SD配置似乎是正确的。

您是否尝试过使用XSdPs_CardInitialize(...)函数而不是自定义的initSD(...)函数? XSdPs_CardInitialize(...)位于sdps驱动程序的xsdps.c中。这个函数正在进行更多的检查,并且还有一些不同的顺序,就像你在initSD(...)中一样。

所以试试这个:

unsigned char initSD(unsigned char sd_id){

if(sd_id > 1) return 0xFF; //only id = 0 or id = 1 is valid

DSTATUS s = 0;
s32 Status;

XSdPs_Config *SdConfig = NULL;

/*
 * Initialize the host controller
 */
SdConfig = &XSdPs_ConfigTable[sd_id];

Status = XSdPs_CfgInitialize(&SdInstance[sd_id], SdConfig, SdConfig->BaseAddress);
if (Status != XST_SUCCESS) {
    s |= STA_NOINIT;
    return s;
}

Status = XSdPs_CardInitialize(&SdInstance[sd_id]);
if (Status != XST_SUCCESS) {
    s |= STA_NOINIT;
    return s;
}

return Status;
}