unsigned int dmaRxCompletion(unsigned short usbDevInst, unsigned int ulEndpoint ) { unsigned int bufferAdd; usbInstance *usbInstance; hostPacketDesc *rx_bd =0; usbInstance = &(cppiInfo.usbInst[usbDevInst]); ulEndpoint = USB_EP_TO_INDEX(ulEndpoint); /*read the compltetion queue */ rx_bd = (hostPacketDesc *)Cppi41DmaReadCompletionQueue(usbDevInst, usbInstance ->rxEndPoint[ulEndpoint].complettionq); bufferAdd = rx_bd->buffAdd; /*Flush the cache to update the buffer */ CacheDataInvalidateBuff(rx_bd->buffAdd, rx_bd->buffLength); putFreeBd(rx_bd); return bufferAdd; }
/** * \brief This function sends the write command to MMCSD card. * * \param mmcsdCtrlInfo It holds the mmcsd control information. * \param ptr It determines the address to where data has to read * \param block It determines from which block data to be read * \param nblks It determines the number of blocks to be read * * \returns 1 - successfull reading of data. * 0 - failure to the data. **/ unsigned int MMCSDReadCmdSend(mmcsdCtrlInfo *ctrl, void *ptr, unsigned int block, unsigned int nblks) { mmcsdCardInfo *card = ctrl->card; unsigned int status = 0; unsigned int address; mmcsdCmd cmd; /* * Address is in blks for high cap cards and in actual bytes * for standard capacity cards */ if (card->highCap) { address = block; } else { address = block * card->blkLen; } ctrl->xferSetup(ctrl, 1, ptr, 512, nblks); cmd.flags = SD_CMDRSP_READ | SD_CMDRSP_DATA | (ctrl->dmaEnable << SD_CMDRSP_DMAEN_OFFSET); cmd.arg = address; cmd.nblks = nblks; if (nblks > 1) { cmd.idx = SD_CMD(18); } else { cmd.idx = SD_CMD(17); } status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { return 0; } status = ctrl->xferStatusGet(ctrl); if (status == 0) { return 0; } #ifdef CACHE /* Invalidate the data cache. */ CacheDataInvalidateBuff((unsigned int)(ptr), 512 * nblks); #endif return 1; }
unsigned int dmaTxCompletion(unsigned short usbDevInst, unsigned int ulEndpoint ) { hostPacketDesc *completed_bd; unsigned int ulRegister; unsigned int state; unsigned int packetid; usbInstance *usbInstance; usbInstance = &(cppiInfo.usbInst[usbDevInst]); ulRegister = USB_O_TXCSRL1 + EP_OFFSET( ulEndpoint); ulEndpoint = USB_EP_TO_INDEX(ulEndpoint); /*read the compltetion queue */ completed_bd = (hostPacketDesc *)Cppi41DmaReadCompletionQueue(usbDevInst, usbInstance ->txEndPoint[ulEndpoint].complettionq); /*Get the packet ID to update the DMA status */ packetid = completed_bd->packetId; if(packetid == EOP) state = DMA_TX_COMPLETED; else state = DMA_TX_IN_PROGRESS; /*wait till Tx completion */ if(state == DMA_TX_COMPLETED) while ((HWREGH(usbInstance->usbBaseAddress + ulRegister) & 0x2) == 0x02); CacheDataInvalidateBuff((unsigned int)completed_bd->buffAdd, sizeof(completed_bd->buffAdd)); cppiDmaFreenBuffer((unsigned int *)completed_bd->buffAdd); completed_bd->buffAdd = 0; /*put the free buffer */ putFreeBd(completed_bd); return state; }
/** * Read or write block(s) from MMC/SD card. The implementation follows * '26.3.5 MMC/SD Mode Single-Block Read Operation Using EDMA' and * '26.3.3 MMC/SD Mode Single-Block Write Operation Using EDMA' in 'spruh82a'. * @param mmcsdCtrlInfo It holds the mmcsd control information. * @param ptr It determines the address to store or fetch the data * @param block It determines from which block data to be read or written (block >= 0) * @param nblks It determines the number of blocks to be read or written (nblks >= 1) * @retval 1 success * @retval 0 fail */ static unsigned int MMCSDReadWriteCmdSend(mmcsdCtrlInfo *ctrl, void *ptr, unsigned int block, unsigned int nblks, bool_t rx) { unsigned int status = 0; // 0 for failure /** * Handle unaligned READ operation using data_recv_buf */ if (rx && ((unsigned int)ptr % SOC_EDMA3_ALIGN_SIZE) != 0) { static uint8_t data_recv_buf[MMCSD_MAX_BLOCK_LEN * 8] __attribute__((aligned(SOC_EDMA3_ALIGN_SIZE))); #define DATA_RECV_BUF_MAX_BLOCKS (sizeof(data_recv_buf) / MMCSD_MAX_BLOCK_LEN) for (unsigned int i = 0; i < nblks; i += DATA_RECV_BUF_MAX_BLOCKS) { unsigned int blocks_to_process = (i + DATA_RECV_BUF_MAX_BLOCKS <= nblks) ? DATA_RECV_BUF_MAX_BLOCKS : nblks - i; status = MMCSDReadWriteCmdSend(ctrl, data_recv_buf, block + i, blocks_to_process, rx); memcpy(ptr + i * MMCSD_MAX_BLOCK_LEN, data_recv_buf, MMCSD_MAX_BLOCK_LEN * blocks_to_process); if (status == 0) break; } goto error_exit; } #if defined(DEBUG_MMCSD) syslog(LOG_NOTICE, "%s(): %s %d block(s), ptr=%p", __FUNCTION__, rx ? "Read" : "Write", nblks, ptr); #endif /* 1. Write the card's relative address to the MMC argument registers (MMCARGH and MMCARGL). */ volatile struct st_mmcsd *mmc = (struct st_mmcsd *)ctrl->memBase; if (!ctrl->card->highCap) { // Only SDHC card is supported by now. syslog(LOG_ERROR, "%s(): Standard capacity SD card is not supported, please use an SDHC card!", __FUNCTION__); goto error_exit; } mmc->MMCARGHL = block; #if 0 mmcsdCardInfo *card = ctrl->card; unsigned int address; /* * Address is in blks for high cap cards and in actual bytes * for standard capacity cards */ assert(card->highCap); if (card->highCap) address = block; else address = block * card->blkLen; mmc->MMCARGHL = address; #endif /* 2. Read card CSD to determine the card's maximum block length. */ // TODO: This step is unnecessary for SDHC card /* 3. Use the MMC command register (MMCCMD) to send the SET_BLOCKLEN command (if the block length is different than the length used in the previous operation). The block length must be a multiple of 512 bytes and less then the maximum block length specified in the CSD. */ // TODO: This step is unnecessary for SDHC card /* 4. Reset the FIFO (FIFORST bit in MMCFIFOCTL). */ mmc->MMCFIFOCTL |= MMCSD_MMCFIFOCTL_FIFORST; mmc->MMCFIFOCTL &= ~MMCSD_MMCFIFOCTL_FIFORST; /* 5. Set the FIFO direction (FIFODIR bit in MMCFIFOCTL). */ if (rx) // FIFO to receive mmc->MMCFIFOCTL &= ~MMCSD_MMCFIFOCTL_FIFODIR; else // FIFO to send mmc->MMCFIFOCTL |= MMCSD_MMCFIFOCTL_FIFODIR; /* 6. Set the access width (ACCWD bits in MMCFIFOCTL). */ mmc->MMCFIFOCTL &= ~MMCSD_MMCFIFOCTL_ACCWD; mmc->MMCFIFOCTL |= (MMCSD_MMCFIFOCTL_ACCWD_4BYTES << MMCSD_MMCFIFOCTL_ACCWD_SHIFT); // => 4 bytes /* 7. Set the FIFO threshold (FIFOLEV bit in MMCFIFOCTL). */ mmc->MMCFIFOCTL |= MMCSD_MMCFIFOCTL_FIFOLEV; // => 64 bytes /* 8. Set up DMA (DMA size needs to be greater than or equal to FIFOLEV setting). */ #if defined(DEBUG_MMCSD) && 0 syslog(LOG_NOTICE, "%s(): Set up DMA", __FUNCTION__); #endif if (rx) { CacheDataCleanBuff(ptr, MMCSD_MAX_BLOCK_LEN * nblks); // Clean 'data_recv_buf' arm926_drain_write_buffer(); // Memory barrier for 'data_recv_buf' ctrl->xferSetup(ctrl, 1, ptr, MMCSD_MAX_BLOCK_LEN, nblks); } else { data_cache_clean_buffer(ptr, MMCSD_MAX_BLOCK_LEN * nblks); // Clean data buffer to send arm926_drain_write_buffer(); // Memory barrier for data buffer to send ctrl->xferSetup(ctrl, 0, ptr, MMCSD_MAX_BLOCK_LEN, nblks); } /* 9. Use MMCCMD to send the READ_BLOCK/WRITE_BLOCK command to the card. */ #if defined(DEBUG_MMCSD) && 0 syslog(LOG_NOTICE, "%s(): Send READ/WRITE command", __FUNCTION__); #endif mmcsdCmd cmd; if (rx) { cmd.flags = SD_CMDRSP_R1 | SD_CMDRSP_READ | SD_CMDRSP_DATA; cmd.idx = SD_CMD(17); cmd.nblks = nblks; if (nblks > 1) { cmd.flags |= SD_CMDRSP_ABORT; cmd.idx = SD_CMD(18); } else { cmd.idx = SD_CMD(17); } } else { cmd.flags = SD_CMDRSP_R1 | SD_CMDRSP_WRITE | SD_CMDRSP_DATA; cmd.idx = SD_CMD(24); cmd.nblks = nblks; if (nblks > 1) { cmd.idx = SD_CMD(25); cmd.flags |= SD_CMDRSP_ABORT; } else { cmd.idx = SD_CMD(24); } } status = MMCSDCmdSend(ctrl, &cmd); if (status == 0) { syslog(LOG_ERROR, "%s(): MMCSDCmdSend() failed.", __FUNCTION__); goto error_exit; } /* 10. Set the DMATRIG bit in MMCCMD to trigger the first data transfer. */ // TODO: This step has already been done by last step. //mmc->MMCCMD |= MMCSD_MMCCMD_DMATRIG; /* 11. Wait for DMA sequence to complete. */ #if defined(DEBUG_MMCSD) && 0 syslog(LOG_NOTICE, "%s(): Wait for DMA sequence to complete", __FUNCTION__); #endif status = ctrl->xferStatusGet(ctrl); if (status == 0) { assert(false); goto error_exit; } if (rx) { // Copy data received CacheDataInvalidateBuff((unsigned int) ptr, MMCSD_MAX_BLOCK_LEN * nblks); // Invalidate the data cache. } /* 12. Use the MMC status register 0 (MMCST0) to check for errors. */ if (rx || nblks == 1) { #if defined(DEBUG_MMCSD) && 0 syslog(LOG_NOTICE, "%s(): Wait for DATDNE", __FUNCTION__); #endif ctrl->waitMMCST0(ctrl, MMCSD_MMCST0_DATDNE); } /* 13. Use MMCCMD to send the STOP_TRANSMISSION command. */ if (cmd.nblks > 1) { #if defined(DEBUG_MMCSD) && 0 syslog(LOG_NOTICE, "%s(): Send STOP_TRANSMISSION", __FUNCTION__); #endif status = MMCSDStopCmdSend(ctrl); assert(status != 0); ctrl->waitMMCST0(ctrl, MMCSD_MMCST0_BSYDNE); //while(HWREG(ctrl->memBase + MMCSD_MMCST1) & MMCSD_MMCST1_BUSY); } error_exit: return status; }
/** * Read block(s) from MMC/SD card. The implementation follows * '26.3.5 MMC/SD Mode Single-Block Read Operation Using EDMA' in 'spruh82a'. * @param mmcsdCtrlInfo It holds the mmcsd control information. * @param ptr It determines the address to where data has to read * @param block It determines from which block data to be read (block >= 0) * @param nblks It determines the number of blocks to be read (nblks >= 1) * @retval 1 success * @retval 0 fail */ unsigned int MMCSDReadCmdSend(mmcsdCtrlInfo *ctrl, void *ptr, unsigned int block, unsigned int nblks) { // TODO: workaround for buggy READ_MULTI_BLOCK if (nblks > 1) { for (unsigned int i = 0; i < nblks; ++i) { unsigned int res = MMCSDReadCmdSend(ctrl, ptr + i * MMCSD_MAX_BLOCK_LEN, block + i, 1); assert(res == 1); } return 1; } assert(nblks == 1); #if defined(DEBUG) // UARTprintf("----\r\n"); // UARTprintf("%s(0x%x)\r\n", __FUNCTION__, ctrl); // syslog(LOG_ERROR, "----"); syslog(LOG_ERROR, "%s(ctrl=0x%p,ptr=0x%p,block=%d,nblks=%d)", __FUNCTION__, ctrl, ptr, block, nblks); #endif assert(nblks * MMCSD_MAX_BLOCK_LEN <= sizeof(data_recv_buf)); // MMCSDDataTimeoutSet(ctrl->memBase, 0x0, 0x3FFFFFF);// Infinite wait for CMD response, maximum wait for data transfer // cmdTimeout = 0; // TODO: fix this (refactoring) // for(int i = 0; i < sizeof(data_recv_buf); ++i) data_recv_buf[i] = 0xFF; // Fill data_recv_buf for debug unsigned int status = 1; // 1 for success volatile struct st_mmcsd *mmc = ctrl->memBase; ER ercd; /* 1. Write the card's relative address to the MMC argument registers (MMCARGH and MMCARGL). */ mmcsdCardInfo *card = ctrl->card; unsigned int address; /* * TODO: check this -- ertl-liyixiao * Address is in blks for high cap cards and in actual bytes * for standard capacity cards */ assert(card->highCap); if (card->highCap) address = block; else address = block * card->blkLen; mmc->MMCARGHL = address; /* 2. Read card CSD to determine the card's maximum block length. */ // TODO: /* 3. Use the MMC command register (MMCCMD) to send the SET_BLOCKLEN command (if the block length is different than the length used in the previous operation). The block length must be a multiple of 512 bytes and less then the maximum block length specified in the CSD. */ // TODO: /* 4. Reset the FIFO (FIFORST bit in MMCFIFOCTL). */ mmc->MMCFIFOCTL |= MMCSD_MMCFIFOCTL_FIFORST; mmc->MMCFIFOCTL &= ~MMCSD_MMCFIFOCTL_FIFORST; /* 5. Set the FIFO direction to receive (FIFODIR bit in MMCFIFOCTL). */ mmc->MMCFIFOCTL &= ~MMCSD_MMCFIFOCTL_FIFODIR; /* 6. Set the access width (ACCWD bits in MMCFIFOCTL). */ mmc->MMCFIFOCTL &= ~MMCSD_MMCFIFOCTL_ACCWD; mmc->MMCFIFOCTL |= (MMCSD_MMCFIFOCTL_ACCWD_4BYTES << MMCSD_MMCFIFOCTL_ACCWD_SHIFT); // => 4 bytes /* 7. Set the FIFO threshold (FIFOLEV bit in MMCFIFOCTL). */ mmc->MMCFIFOCTL |= MMCSD_MMCFIFOCTL_FIFOLEV; // => 64 bytes /* 8. Set up DMA (DMA size needs to be greater than or equal to FIFOLEV setting). */ CacheDataCleanBuff(data_recv_buf, sizeof(data_recv_buf)); // Clean 'data_recv_buf' arm926_drain_write_buffer(); // Memory barrier for 'data_recv_buf' ctrl->xferSetup(ctrl, 1, data_recv_buf/*ptr*/, MMCSD_MAX_BLOCK_LEN, nblks); /* 9. Use MMCCMD to send the READ_BLOCK command to the card. */ #if defined(DEBUG) syslog(LOG_ERROR, "%s(): Use MMCCMD to send the READ_BLOCK/READ_MULTI_BLOCK command to the card.", __FUNCTION__); #endif // ercd = clr_flg(MMCSD_ISR_FLG, ~(MMCSD_ISR_FLGPTN_DATATIMEOUT)); // Clear data time-out flag // mmc->MMCIM |= MMCSD_MMCIM_ETOUTRD; // Enable data time-out interrupt assert(ercd == E_OK); mmcsdCmd cmd; cmd.flags = SD_CMDRSP_R1 | SD_CMDRSP_READ | SD_CMDRSP_DATA; cmd.arg = address; cmd.nblks = nblks; if (nblks > 1) { cmd.flags |= SD_CMDRSP_ABORT; cmd.idx = SD_CMD(18); } else { cmd.idx = SD_CMD(17); } status = MMCSDCmdSend(ctrl, &cmd); if (status == 0) { syslog(LOG_ERROR, "%s(): MMCSDCmdSend() failed.", __FUNCTION__); goto error_exit; } /* 10. Set the DMATRIG bit in MMCCMD to trigger the first data transfer. */ #if DEBUG_PRINT // syslog(LOG_ERROR, "%s(): Set the DMATRIG bit, MMCCMD: 0x%08x=>0x%08x", __FUNCTION__, mmc->MMCCMD, mmc->MMCCMD | MMCSD_MMCCMD_DMATRIG); #endif // mmc->MMCCMD /*|*/= MMCSD_MMCCMD_DMATRIG; /* 11. Wait for DMA sequence to complete. */ status = ctrl->xferStatusGet(ctrl); if (status == 0) { assert(false); goto error_exit; } /* Invalidate the data cache. */ CacheDataInvalidateBuff((unsigned int) data_recv_buf/*ptr*/, (MMCSD_MAX_BLOCK_LEN * nblks)); /* 12. Use the MMC status register 0 (MMCST0) to check for errors. */ // TODO: check this #if 0 syslog(LOG_ERROR, "%s(): MMCST0: 0x%08x", __FUNCTION__, mmc->MMCST0); syslog(LOG_ERROR, "%s(): MMCST1: 0x%08x", __FUNCTION__, mmc->MMCST1); syslog(LOG_ERROR, "%s(): MMCNBLK: %d", __FUNCTION__, mmc->MMCNBLK); syslog(LOG_ERROR, "%s(): MMCNBLC: %d", __FUNCTION__, mmc->MMCNBLC); #endif assert(sizeof(data_recv_buf) >= MMCSD_MAX_BLOCK_LEN * nblks); memcpy(ptr, data_recv_buf, MMCSD_MAX_BLOCK_LEN * nblks); // TODO: ertl-liyixiao #if defined(DEBUG) syslog(LOG_ERROR, "%s sector: %d, count: %d\n", __FUNCTION__, block, nblks); for(int i = 0; i < MMCSD_MAX_BLOCK_LEN * nblks;) { //((uint8_t*)ptr)[i] = ((uint8_t*)ptr)[i]; uint8_t *val = ((uint8_t*)ptr) + i; syslog(LOG_ERROR, "%02x %02x %02x %02x %02x", val[0], val[1], val[2], val[3], val[4]); //printf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x \n", // val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], val[12], val[13], val[14], val[15]); i += 5; } #endif #if 0 // TODO: !IMPORTANT! STOP_TRANSMISSION must not be sent since MMCSD_MMCNBLK has been set to the exact number. /* Send a STOP_TRANSMISSION after reading multiple blocks */ if (cmd.nblks > 1) { status = MMCSDStopCmdSend(ctrl); assert(status != 0); // TODO: check status } #endif error_exit: // mmc->MMCIM &= ~MMCSD_MMCIM_ETOUTRD; // Disable data time-out interrupt TODO: fix me return status; #if 0 // TODO: -- ertl-liyixiao #ifdef CACHE_SUPPORTED /* Clean the data cache. */ CacheDataCleanBuff((unsigned int) ptr, (MMCSD_MAX_BLOCK_LEN * nblks)); #endif mmcsd_reset_fifo(true); /* Send a STOP */ if (cmd.nblks > 1) { status = MMCSDStopCmdSend(ctrl); if (status == 0) { #if DEBUG_PRINT UARTprintf("%s(0x%x):MMCSDStopCmdSend() returned 0\r\n", __FUNCTION__, ctrl); #endif return 0; } } #endif }
unsigned int MMCSDCardInit(mmcsdCtrlInfo *ctrl) { mmcsdCardInfo *card = ctrl->card; unsigned int retry = 0xFFFF; unsigned int status = 0; unsigned int khz; mmcsdCmd cmd; memset(ctrl->card, 0, sizeof(mmcsdCardInfo)); card->ctrl = ctrl; /* CMD0 - reset card */ status = MMCSDCardReset(ctrl); if (status == 0) { card->error = 1; return 0; } //mmc card initialization ctrl->card->cardType = MMCSD_CARD_MMC; //open drain для команд инициализации HWREG(ctrl->memBase + MMCHS_CON) |= MMCHS_CON_OD; //Set SD_SYSCTL[25] SRC //bit to 0x1 and wait until it returns to 0x0 HWREG(ctrl->memBase + MMCHS_SYSCTL) |= MMCHS_SYSCTL_SRC; while(!(HWREG(ctrl->memBase + MMCHS_SYSCTL) & MMCHS_SYSCTL_SRC)); while(HWREG(ctrl->memBase + MMCHS_SYSCTL) & MMCHS_SYSCTL_SRC); /* CMD1 - SEND_OP_COND */ retry = RETRY; //с потолка cmd.idx = SD_CMD(1); cmd.flags = 0; cmd.arg = 0x40ff8080;/////карта больше 2 Гб? cmd.rsp[0] = 0; do{ status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; //если нет ответа, можно выходить } //добавил задержку для кривой eMMC СОТА delay(10); } while (!(cmd.rsp[0] & ((unsigned int)BIT(31))) && retry--); if (0xffffffff == retry) //карта до 2 Гб? { retry = RETRY; //c потолка cmd.arg = 0x00ff8080; //волшебная цыфорка do{ status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; //если нет ответа, можно выходить } //добавил задержку для кривой eMMC СОТА delay(10); } while (!(cmd.rsp[0] & ((unsigned int)BIT(31))) && retry--); } if (0xffffffff == retry) { card->error = 1; return 0; } //сохраняем OCR card->ocr = cmd.rsp[0]; card->highCap = (card->ocr & SD_OCR_HIGH_CAPACITY) ? 1 : 0; /* CMD2 - ALL_SEND_CID */ cmd.idx = SD_CMD(2); cmd.flags = SD_CMDRSP_136BITS; cmd.arg = 0; status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; //если нет ответа, можно выходить } //Сохраняем CID карты memcpy(card->raw_cid, cmd.rsp, 16); /* CMD3 - SET_RELATIVE_ADDR */ cmd.idx = SD_CMD(3); cmd.flags = 0; cmd.arg = 2 << 16; status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; //если нет ответа, можно выходить } card->rca = 2; //тупо //вырубаем open drain для команд инициализации HWREG(ctrl->memBase + MMCHS_CON) &= ~MMCHS_CON_OD; /* Send CMD9, to get the card specific data */ cmd.idx = SD_CMD(9); cmd.flags = SD_CMDRSP_136BITS; cmd.arg = card->rca << 16; status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; //если нет ответа, можно выходить } memcpy(card->raw_csd, cmd.rsp, 16); card->sd_ver = SD_CARD_CSD_VERSION(card); card->tranSpeed = SD_CARD0_TRANSPEED(card); //Меняем тактовую частоту на повыше //если где-то еще используется - запихнуть в функцию switch (card->tranSpeed & 0x00000007) { case 0: khz = 100e3; break; case 1: khz = 1000e3; break; case 2: khz = 10000e3; break; case 3: khz = 100000e3; break; default: UARTPuts("TRAN_SPEED incorrect value read", -1); card->error = 1; return 0; } switch ((card->tranSpeed) >> 3) { case 1: ctrl->opClk = 1 * khz; break; case 2: ctrl->opClk = 1.2 * khz; break; case 3: ctrl->opClk = 1.3 * khz; break; case 4: ctrl->opClk = 1.5 * khz; break; case 5: ctrl->opClk = 2 * khz; break; case 6: ctrl->opClk = 2.6 * khz; break; case 7: ctrl->opClk = 3 * khz; break; case 8: ctrl->opClk = 3.5 * khz; break; case 9: ctrl->opClk = 4 * khz; break; case 10: ctrl->opClk = 4.5 * khz; break; case 11: ctrl->opClk = 5.2 * khz; break; case 12: ctrl->opClk = 5.5 * khz; break; case 13: ctrl->opClk = 6 * khz; break; case 14: ctrl->opClk = 7 * khz; break; case 15: ctrl->opClk = 8 * khz; break; default: UARTPuts("TRAN_SPEED incorrect value read", -1); card->error = 1; return 0; } status = ctrl->busFreqConfig(ctrl, ctrl->opClk); if (status != 0) //эта функция возвращает ноль при успехе { card->error = 1; UARTPuts("HS MMC/SD TRAN_SPEED freqval set failed\n\r", -1); return 0; } //если спецификация вер. 4.0 и выше if (card->sd_ver > 3) { /* Send CMD7 select card */ cmd.idx = SD_CMD(7); cmd.flags = 0; //ответ R1 cmd.arg = card->rca << 16; status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; } #if 0 //говнокод if ((cmd.rsp[0] & BIT(25))) //если карта залочена стираем нафиг с нее все { //устанавливаем длину блока 1 байт /* Send CMD16 */ cmd.idx = SD_CMD(16); cmd.flags = 0; //ответ R1 cmd.arg = 1; //1 байт длина блока status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; } dataBuffer[0] = BIT(3); //Force-erase bit dataBuffer[1] = 0; //Force-erase bit dataBuffer[2] = 0; //Force-erase bit dataBuffer[3] = BIT(3); //Force-erase bit #ifdef CACHE /* Invalidate the data cache. */ CacheDataCleanBuff((unsigned int)dataBuffer, 4); #endif ctrl->xferSetup(ctrl, 0/*0 - WRITE*/, dataBuffer, 1, 1); //Achtung! посылка одного байта cmd.idx = SD_CMD(42); cmd.flags = SD_CMDRSP_WRITE | SD_CMDRSP_DATA | (ctrl->dmaEnable << SD_CMDRSP_DMAEN_OFFSET); cmd.arg = 0; cmd.nblks = 1; cmd.data = (signed char*)dataBuffer; status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; } status = ctrl->xferStatusGet(ctrl); // if (status == 0) return 0; //проверяем статус карты cmd.idx = SD_CMD(13); cmd.flags = 0; //ответ R1 cmd.arg = card->rca << 16; //1 байт длина блока status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; } //ждем пока карта не снимет busy! while (!(HWREG(ctrl->memBase + MMCHS_PSTATE) & (unsigned int)BIT(20))); //возвращаем длину блока в нормальное состояние /* Send CMD16 */ cmd.idx = SD_CMD(16); cmd.flags = 0; //ответ R1 cmd.arg = 512; //512 байт длина блока status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; } while(1); } #endif //надо затянуть EXT_CSD ctrl->xferSetup(ctrl, 1, dataBuffer, 512, 1); cmd.idx = SD_CMD(8); cmd.flags = SD_CMDRSP_READ | SD_CMDRSP_DATA | (ctrl->dmaEnable << SD_CMDRSP_DMAEN_OFFSET); cmd.arg = 0; cmd.nblks = 1; cmd.data = (signed char*)dataBuffer; status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; } status = ctrl->xferStatusGet(ctrl); if (status == 0) { card->error = 1; return status; } #ifdef CACHE /* Invalidate the data cache. */ CacheDataInvalidateBuff((unsigned int)dataBuffer, DATA_RESPONSE_WIDTH); #endif } else { UARTPuts("Old Slowpoke eMMC card\n\r", -1); } //разное определение размера карты для highCap карт и обычных карт if (!(card->highCap)) { //не факт, что работает для !highCap card->blkLen = 1 << (SD_CARD0_RDBLKLEN(card)); card->size = SD_CARD0_SIZE(card); card->nBlks = card->size / card->blkLen; /* Set data block length to 512 (for byte addressing cards) */ if (card->blkLen != 512) { cmd.idx = SD_CMD(16); cmd.flags = 0; //resp R1 cmd.arg = 512; status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) { card->error = 1; return status; } else { card->blkLen = 512; } } } else //highcap - берем sector size из EXT_CSD { //надо сохранить нужную инфу из EXT_CSD на будущее //пока только SEC_COUNT card->blkLen = 512; card->nBlks = (dataBuffer[212] << 0) | (dataBuffer[213] << 8) | (dataBuffer[214] << 16) | (dataBuffer[215] << 24); card->size = card->nBlks; //для highcap карты размер в секторах } card->busWidth = 1; #if 0 //деселект рабочий но забили на него - карта у нас одна //deselect card /* Send CMD7 select card */ cmd.idx = SD_CMD(7); cmd.flags = SD_CMDRSP_NONE; //ответ R1 cmd.arg = 0; //rca = 0 status = ctrl->cmdSend(ctrl, &cmd); if (status == 0) return status; #endif //end emmc initialization return 1; }