------------------------------ РЕДАКТИРОВАТЬ: Дополнительное примечание ----------------- ----------
Мы только что попытались перейти только на Vivado 2016.1. В этой версии SD-карта работает с новыми функциями, даже если каким-то образом разрушает аудиокодек. Что довольно интересно, потому что мы просмотрели все примечания к патчу с 2015.2 по 2016.4, и единственное, что упоминалось, это то, что они добавили дополнительный тип данных для ввода-вывода SD-карты, который снова будет удален в следующей версии.
----------------КОНЕЦ РЕДАКТИРОВАТЬ-------------------------------- ------------------------
Мы только что перенесли наш проект робота с vivado 2015.2 на 2016.4, после обновления образ SD мигает, когда запускается fpga (zynq 7020), но код процессора не будет выполняться. После некоторой отладки мы обнаружили, что нам нужно создать новый проект SDK с новыми FSBL и BSP и включить исходные файлы с новым пустым приложением. После этого программа зациклилась, и нам пришлось отлаживать дальше. Затем мы узнали, что нам пришлось заменить наши фактические функции 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:
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-карте. Кроме того, мы обнаружили, что при инициализации SD функция getBusWidth (bsp) дает сбой при попытке вызвать XSdPs_CmdTransfer() -> XSdPs_ReadReg(). Это также похоже на тот случай, когда мы пытаемся выполнять операции ввода-вывода на SD-карте с нашими старыми функциями.
Функция инициализации 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;
}
После этого довольно краткого описания нашей проблемы ;), теперь к моему вопросу. Кто-нибудь из вас сталкивался с подобной проблемой и знает обходной путь или может указать нам направление, в котором мы можем найти решение?
Заранее спасибо :).
Удалить0r