void sd_card_test(void); int main() { sd_card_test(); } uint8_t const CMD0 = 0X00; /** SEND_IF_COND - verify SD Memory Card interface operating condition.*/ uint8_t const CMD8 = 0X08; /** SEND_CSD - read the Card Specific Data (CSD register) */ uint8_t const CMD9 = 0X09; /** SEND_CID - read the card identification information (CID register) */ uint8_t const CMD10 = 0X0A; /** SEND_STATUS - read the card status register */ uint8_t const CMD13 = 0X0D; /** READ_BLOCK - read a single data block from the card */ uint8_t const CMD17 = 0X11; /** WRITE_BLOCK - write a single data block to the card */ uint8_t const CMD24 = 0X18; /** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */ uint8_t const CMD25 = 0X19; /** ERASE_WR_BLK_START - sets the address of the first block to be erased */ uint8_t const CMD32 = 0X20; /** ERASE_WR_BLK_END - sets the address of the last block of the continuous range to be erased*/ uint8_t const CMD33 = 0X21; /** ERASE - erase all previously selected blocks */ uint8_t const CMD38 = 0X26; /** APP_CMD - escape for application specific command */ uint8_t const CMD55 = 0X37; /** READ_OCR - read the OCR register of a card */ uint8_t const CMD58 = 0X3A; /** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be pre-erased before writing */ uint8_t const ACMD23 = 0X17; /** SD_SEND_OP_COMD - Sends host capacity support information and activates the card's initialization process */ uint8_t const ACMD41 = 0X29; //------------------------------------------------------------------------------ /** status for card in the ready state */ uint8_t const R1_READY_STATE = 0X00; /** status for card in the idle state */ uint8_t const R1_IDLE_STATE = 0X01; /** status bit for illegal command */ uint8_t const R1_ILLEGAL_COMMAND = 0X04; /** start data token for read or write single block*/ uint8_t const DATA_START_BLOCK = 0XFE; /** stop token for write multiple blocks*/ uint8_t const STOP_TRAN_TOKEN = 0XFD; /** start data token for write multiple blocks*/ uint8_t const WRITE_MULTIPLE_TOKEN = 0XFC; /** mask for data response tokens after a write block operation */ uint8_t const DATA_RES_MASK = 0X1F; /** write data accepted token */ uint8_t const DATA_RES_ACCEPTED = 0X05; uint8_t status_ = 0; static void spiSend(uint8_t b) { spi_transfer(b); } /** Receive a byte from the card */ static uint8_t spiRec(void) { return spi_transfer(0xFF); } uint32_t millis() { return msTicks; } uint8_t waitNotBusy(unsigned int timeoutMillis) { unsigned int t0 = millis(); unsigned int d; do { if (spiRec() == 0XFF) { return true; } d = millis() - t0; } while (d < timeoutMillis); return false; } void chipSelectLow() { spi_ss(0); } uint8_t cardCommand(uint8_t cmd, uint32_t arg) { // select card chipSelectLow(); // wait up to 300 ms if busy waitNotBusy(300); // send command spiSend(cmd | 0x40); // send argument for (int8_t s = 24; s >= 0; s -= 8) { spiSend(arg >> s); } // send CRC uint8_t crc = 0XFF; if (cmd == CMD0) { crc = 0X95; // correct crc for CMD0 with arg 0 } if (cmd == CMD8) { crc = 0X87; // correct crc for CMD8 with arg 0X1AA } spiSend(crc); // wait for response for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++) ; return status_; } static void sd_card_test(void) { bool inserted = false; debug_printf("--- SD Card Test ---\n"); inserted = !HAL_GPIO_CD_read(); debug_printf("SD Card is %s\n", inserted ? "inserted" : "not inserted"); if (inserted) { unsigned int t0 = millis(); for (uint8_t i = 0; i < 10; i++) { spiSend(0XFF); } spi_ss(0); bool error = false; while ((status_ = cardCommand(CMD0, 0)) != 0x01) { unsigned int d = millis() - t0; if (d > 2000) { error = true; break; } } if (error) { debug_printf("Failure :(\n"); } else { debug_printf("SUCCESS !\n"); } spi_ss(1); } }