2017-03-13 171 views
3

---------------編輯:額外注意------------- ----------------------------從Vivado 2015.2到2016.4遷移後初始化和使用SD卡不起作用

我們只試過遷移到Vivado 2016.1。使用該版本的SD卡即使在某種程度上破壞了音頻編解碼器的情況下也能夠使用新功能。這非常有趣,因爲我們查看了2015.2到2016.4的每個補丁說明,唯一提到的是他們爲sd卡I/O增加了一個額外的數據類型,在下一個版本中再次取出它。

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

我們剛剛將我們的機器人項目從vivado 2015.2遷移到2016.4,升級後的sd圖像在fpga(zynq 7020)開始運行時閃存,但處理器代碼不會執行。經過一些調試後,我們發現,我們必須用新的FSBL和BSP創建一個新的SDK項目,並在源文件中包含一個新的空應用程序。之後,程序陷入循環,所以我們不得不進一步調試。然後我們發現我們必須用我們的舊SD卡替換我們的實際SD卡功能(在TRM UG585中推薦的功能)。

新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函數y:

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; 
    } 

這個固定與一般的處理器代碼的問題,但我們仍無法初始化或在做IO操作SD卡。另外我們發現當初始化SD時,函數getBusWidth(bsp)在嘗試調用XSdPs_CmdTransfer() - > 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

回答

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; 
} 
+0

感謝很多:)。一旦我再次訪問硬件,我會嘗試它。 – Delet0r

0

我們還與Vivado 2016.3這就爲SD卡,即使我們不知道爲什麼工作的嘗試。我們還沒有檢查過其他方面是否有效,但現在看起來似乎是一種解決方法。

希望它被固定在2017.1