static uint8 send_slow_cmd ( uint8 cmd, /* Command byte */ uint32 arg /* Argument */ ) { uint8 n, res; uint8 cb[6]; int i; (void)spi_slow_sr_byte(0xff); i = 0; do { res = spi_slow_sr_byte(0xff); i++; } while ((res != 0xFF) && i < 100000); if (res != 0xff) { #ifdef SD_DEBUG dbglog(DBG_DEBUG, "%s: CMD 0x%02x error\n", __func__, cmd); #endif return(0xff); } cb[0] = cmd; cb[1] = (uint8)(arg >> 24); cb[2] = (uint8)(arg >> 16); cb[3] = (uint8)(arg >> 8); cb[4] = (uint8)arg; cb[5] = sd_crc7(cb, 5, 0); /* Send command packet */ spi_slow_sr_byte(cmd); /* Command */ spi_slow_sr_byte(cb[1]); /* Argument[31..24] */ spi_slow_sr_byte(cb[2]); /* Argument[23..16] */ spi_slow_sr_byte(cb[3]); /* Argument[15..8] */ spi_slow_sr_byte(cb[4]); /* Argument[7..0] */ spi_slow_sr_byte(cb[5]); // CRC7 /* Receive command response */ if (cmd == CMD12) (void)spi_slow_sr_byte(0xff);/* Skip a stuff byte when stop reading */ n = 20; /* Wait for a valid response in timeout of 10 attempts */ do { res = spi_slow_sr_byte(0xff); } while ((res & 0x80) && --n); #ifdef SD_DEBUG dbglog(DBG_DEBUG, "%s: CMD 0x%02x response 0x%02x\n", __func__, cmd, res); #endif return res; /* Return with the response value */ }
/** * \ingroup sd_raw * Send a command to the memory card which responses with a R1 response (and possibly others). * * \param[in] command The command to send. * \param[in] arg The argument for command. * \returns The command answer. */ uint8_t sd_raw_send_command(uint8_t command, uint32_t arg) { uint8_t response; uint8_t *args = reinterpret_cast<uint8_t *>(&arg); /* wait some clock cycles */ sd_raw_rec_byte(); #if !SD_RAW_SAVE_RAM if ( sd_use_crc ) { uint8_t crc[6] = { command | 0x40, args[3], args[2], args[1], args[0] }; crc[5] = sd_crc7(crc, 5); for (uint8_t i = 0; i < 6; i++) sd_raw_send_byte(crc[i]); } else { #endif /* send command via SPI */ sd_raw_send_byte(0x40 | command); for (int8_t i = 3; i >= 0; i--) sd_raw_send_byte(args[i]); switch(command) { case CMD_GO_IDLE_STATE: sd_raw_send_byte(0x95); break; case CMD_SEND_IF_COND: sd_raw_send_byte(0x87); break; default: sd_raw_send_byte(0xff); break; } #if !SD_RAW_SAVE_RAM } #endif /* receive response */ for(uint8_t i = 0; i < 10; ++i) { response = sd_raw_rec_byte(); if(response != 0xff) break; } return response; }