byte MMC_ReadOCR(byte cmd, uint32_t param, byte* ocr) { byte r = MMC_Command(cmd,param); byte i = 4; while (i--) *ocr++ = SPI_ReceiveByte(0xFF); return r; }
byte MMC_ReadSector(byte *buffer, uint32_t sector) { if (!(_mmcState & MMC_INITED)) return MMC_NOT_INITED; if (!(_mmcState & MMC_HIGH_DENSITY)) sector <<= 9; MMC_SS_LOW(); if (MMC_Command(17,sector) != 0 || MMC_Token() != 0xFE) return MMC_Release(READ_FAILED); SPI_Receive(buffer,512); // WARNING! Will strip 2 CRC bytes as well return MMC_Release(0); }
byte MMC_Init2() { byte ocr[4]; MMC_SS_HIGH(); // SPI_Init(); // Init slow at first TODO _mmcState = 0; // initialize the MMC card into SPI mode by sending 80 clks int i; for (i = 0; i < 10; i++) SPI_ReceiveByte(0xFF); // Send GO_IDLE_STATE MMC_SS_LOW(); if (MMC_Command(0,0) != 1) return GO_IDLE_TIMEOUT; _mmcState = MMC_PRESENT; MMC_SS_HIGH(); // Full speed SPI_Enable(); MMC_SS_LOW(); if (MMC_ReadOCR(58,0,ocr) != 1) // Read OCR check voltages return READ_OCR_TIMEOUT; // Can't read OCR if ((ocr[1] & 0x10) == 0) return BAD_VOLTAGE; // Card does not like out voltage // Try CMD8 if (MMC_ReadOCR(8,0x1AA,ocr) == 1) { // SDHC _mmcState |= MMC_SDHC; if ((ocr[2] & 0x0F) != 1) return BAD_VOLTAGE; // Card does not like out voltage if (ocr[3] != 0xAA) return BAD_PATTERN; // Send ACMD41 and wait for it to come out of idle i = 0x7FFF; // Wait a long time. A long, long time - some cards take 700 miliseconds or more. while (i--) { MMC_Command(55,0); // SEND_APP_CMD if (MMC_Command(41,1L << 30) == 0) // ACMD41 with HCS bit 30 set break; } if (i < 0) return OP_COND_TIMEOUT; // Check density again if (MMC_ReadOCR(58,0,ocr) != 0) // Bits[30:29]=1,0 return READ_OCR_TIMEOUT; // Can't read OCR if ((ocr[0] & 0x60) == 0x40) _mmcState |= MMC_HIGH_DENSITY; } else { // SDCARD 1vXX // Send SEND_OP_COND and wait for it to come out of idle i = 0x7FFF; while (i--) { if ((MMC_Command(1,0) & 1) == 0) break; } if (i < 0) return OP_COND_TIMEOUT; } // Send SET_BLOCKLEN for 512 byte block if (MMC_Command(16,512) != 0) return SET_BLOCKLEN_TIMEOUT; _mmcState |= MMC_INITED; return 0; }