uint32_t identifyCard( void ) { // NOTE: see OMAP35x.pdf page 3164, starterware and sd_spec 2.0 uint8_t hcsFlag = 0; memset( &cardInfo, 0, sizeof( CARD_INFO ) ); // send GO_IDLE_STATE if ( sendCmd0() ) { // an error occured sending CMD0 return 1; } // cmd5 is reserved for I/O cards: SDIO. will return 0 if it is SDIO if ( 0 == sendCmd5() ) { return 1; } // send GO_IDLE_STATE again if ( sendCmd0() ) { // an error occured sending CMD0 return 1; } // send SEND_IF_COND if ( 0 == sendCmd8() ) { // NOTE: it is an SD card compliant with standard 2.0 or later uint32_t rsp0 = MMCHS_RSP10 & 0x0000FFFF; uint32_t supportedVoltage = rsp0 & 0xFFF; if ( supportedVoltage != 0x1AA ) { // NOT supported: return 1; } hcsFlag = TRUE; } while ( 1 ) { // send SD_SEND_OP_COND // NOTE: sd_spec 2.0 page 26: While repeating ACMD41, the host shall not issue another command except CMD0. => other sources say repeat CMD55 too if ( 0 == sendACmd41( hcsFlag ) ) { // if card is busy, repeat again, otherwise card is identified if ( ! isCardBusy() ) { // NOTE: it is a SD card compliant with standard 1.x // store ocr in card-info cardInfo.ocr = MMCHS_RSP10; // check if card is high-capacity or not (HCR-bit in OCR at position 30) cardInfo.highCap = ( cardInfo.ocr & ( 1 << 30 ) ) ? 1 : 0; goto cardIdentified; } } // no response => its no SD meory card else { break; } } // NOTE: at this point we are a MMC card - we don't support them return 1; cardIdentified: // send ALL_SEND_CID if ( sendCmd2() ) { return 1; } // store card-info just returned by CMD2 in RSP10-76 cardInfo.raw_cid[ 0 ] = MMCHS_RSP10; cardInfo.raw_cid[ 1 ] = MMCHS_RSP32; cardInfo.raw_cid[ 2 ] = MMCHS_RSP54; cardInfo.raw_cid[ 3 ] = MMCHS_RSP76; // send SEND_RELATIVE_ADDR to ask card to publish new realtive address if ( sendCmd3() ) { return 1; } // store RCA just returned by CMD3 cardInfo.rca = ( MMCHS_RSP10 & 0xFFFF0000 ) >> 16; // send SEND_CSD: request card-specific data if ( sendCmd9() ) { return 1; } // store card-specific data just returned by CMD9 in RSP10-76 cardInfo.raw_csd[ 0 ] = MMCHS_RSP10; cardInfo.raw_csd[ 1 ] = MMCHS_RSP32; cardInfo.raw_csd[ 2 ] = MMCHS_RSP54; cardInfo.raw_csd[ 3 ] = MMCHS_RSP76; if ( SD_CARD_CSD_VERSION( cardInfo ) ) { cardInfo.tranSpeed = SD_CARD1_TRANSPEED(cardInfo); cardInfo.blkLen = 1 << (SD_CARD1_RDBLKLEN(cardInfo)); cardInfo.size = SD_CARD1_SIZE(cardInfo); cardInfo.nBlks = cardInfo.size / cardInfo.blkLen; } else { cardInfo.tranSpeed = SD_CARD0_TRANSPEED(cardInfo); cardInfo.blkLen = 1 << (SD_CARD0_RDBLKLEN(cardInfo)); cardInfo.nBlks = SD_CARD0_NUMBLK(cardInfo); cardInfo.size = SD_CARD0_SIZE(cardInfo); } // send SELECT/DESELECT_CARD to select card - now in transfer mode if ( sendCmd7() ) { return 1; } // NOTE: at this point the card is initialized, identified and ready to be used // send block length only in case of standard capacity-card, send it ONCE after selection if ( ! cardInfo.highCap ) { // send block length if ( sendCmd16() ) { // an error occured during sending the command, return immediately return 1; } } // request SCR - will be transmitted throug a data-read! if ( sendACmd51() ) { return 1; } uint8_t scrBuffer[ 8 ]; memset( scrBuffer, 0, 8 ); // SCR is transmitted in 8 bytes through a data-read if ( readTransferBuffer( 8, scrBuffer ) ) { return 1; } cardInfo.raw_scr[ 0 ] = ( scrBuffer[ 3 ] << 24 ) | ( scrBuffer[ 2 ] << 16 ) | ( scrBuffer[ 1 ] << 8 ) | ( scrBuffer[ 0 ] ); cardInfo.raw_scr[ 1 ] = ( scrBuffer[ 7 ] << 24 ) | ( scrBuffer[ 6 ] << 16 ) | ( scrBuffer[ 5 ] << 8 ) | ( scrBuffer[ 4 ] ); cardInfo.sd_ver = SD_CARD_VERSION( cardInfo ); cardInfo.busWidth = SD_CARD_BUSWIDTH( cardInfo ); return 0; }
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; }