Exemplo n.º 1
0
//------------------------------------------------------------------------------
// send command to card
uint8_t SdReader::cardCommand(uint8_t cmd, uint32_t arg) {
//Serial.print("cardCommand, cmd="); Serial.print(cmd, DEC); Serial.print(", arg="); Serial.println(arg, DEC);
  uint8_t r1;
  
  // end read if in partialBlockRead mode
  readEnd();
  
  // select card
  spiSSLow();
  
  // 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 retry = 0; ((r1 = spiRec()) & 0X80) && retry != 0XFF; retry++);

  return r1;
}
/**
 * Initialize a SD flash memory card.
 * 
 * \param[in] slow Set SPI Frequency F_CPU/4 if true else F_CPU/2. 
 *  
 * \return The value one, true, is returned for success and
 * the value zero, false, is returned for failure. 
 *
 */  
uint8_t SdCard::init(uint8_t slow)
{
  pinMode(SS, OUTPUT);
  spiSSHigh();
  pinMode(MOSI, OUTPUT);
  pinMode(SCK, OUTPUT);
  //Enable SPI, Master, clock rate F_CPU/128
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
  //must supply min of 74 clock cycles with CS high.
  for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
  spiSSLow();
  // next line prevent re-init hang by some cards (not sure why this works)
  for (uint16_t i = 0; i <= 512; i++) spiRec();
  uint8_t r = cardCommand(CMD0, 0);
  for (uint16_t retry = 0; r != R1_IDLE_STATE; retry++){
    if (retry == 10000) {
      error(SD_ERROR_CMD0, r);
      return false;
    }
    r = spiRec();
  }
  for (uint16_t retry = 0; ; retry++) {
    cardCommand(CMD55, 0);
    if ((r = cardCommand(ACMD41, 0)) == R1_READY_STATE)break;
    if (retry == 1000) {
      error(SD_ERROR_ACMD41, r);
      return false;
    }
  }
  // set SPI frequency
  SPCR &= ~((1 << SPR1) | (1 << SPR0)); // F_CPU/4
  if (!slow) SPSR |= (1 << SPI2X); // Doubled Clock Frequency to F_CPU/2
  spiSSHigh();
  return true;
}
Exemplo n.º 3
0
//------------------------------------------------------------------------------
// send command to card
uint8_t sdCardCommand(uint8_t cmd, uint32_t arg) {
   uint8_t r1;
   uint8_t retry;
   signed char s;

   // end read if in partialBlockRead mode
   sdReadEnd();

   // select card
   spiSSLow();

   // wait up to 300 ms if busy
   sdWaitNotBusy(300);

   // send command
   spiSend(cmd | 0x40);

   // send argument
   for (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 (retry = 0; ((r1 = spiRec()) & 0X80) && retry != 0XFF; retry++);

   return r1;
}
//------------------------------------------------------------------------------
static uint8_t cardCommand(uint8_t cmd, uint32_t arg)
{
  uint8_t r1;
  // some cards need extra clocks after transaction to go to ready state
  // easiest to put extra clocks before next transaction
  spiSSLow();
  spiRec();
  spiSend(cmd | 0x40);
  for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);
  spiSend(cmd == CMD0 ? 0x95 : 0XFF);//must send valid CRC for CMD0
  //wait for not busy
  for (uint8_t retry = 0; (r1 = spiRec()) == 0xFF && retry != 0XFF; retry++);
  return r1;
}
Exemplo n.º 5
0
/**
 * Initialize a SD flash memory card.
 *
 * \param[in] slow If \a slow is false (zero) the SPI bus will
 * be initialize at a speed of 8 Mhz.  If \a slow is true (nonzero)
 * the SPI bus will be initialize a speed of 4 Mhz. This may be helpful
 * for some SD cards with Version 1.0 of the Adafruit Wave Shield.
 *
 * \return The value one, true, is returned for success and
 * the value zero, false, is returned for failure. 
 *
 */  
uint8_t SdReader::init(uint8_t slow) {
  uint8_t ocr[4];
  uint8_t r;
  
  pinMode(SS, OUTPUT);
  digitalWrite(SS, HIGH);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO_PIN, INPUT);
  pinMode(SCK, OUTPUT);
  
#if SPI_INIT_SLOW
  // Enable SPI, Master, clock rate f_osc/128
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
#else  // SPI_INIT_SLOW
  // Enable SPI, Master, clock rate f_osc/64
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
#endif  // SPI_INIT_SLOW
  
  // must supply min of 74 clock cycles with CS high.
  for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
  
  // next two lines prevent re-init hang by cards that were in partial read
  spiSSLow();
  for (uint16_t i = 0; i <= 512; i++) spiRec();
  
  // command to go idle in SPI mode
  for (uint8_t retry = 0; ; retry++) {
    if ((r = cardCommand(CMD0, 0)) ==  R1_IDLE_STATE) break;
    if (retry == 10) {
      error(SD_CARD_ERROR_CMD0, r);
      return false;
    }
  }
  // check SD version
  r = cardCommand(CMD8, 0x1AA);
  if (r == R1_IDLE_STATE) {
    for(uint8_t i = 0; i < 4; i++) {
      r = spiRec();
    }
    if (r != 0XAA) {
      error(SD_CARD_ERROR_CMD8_ECHO, r);
      return false;
    }
    type(SD_CARD_TYPE_SD2);
  }
  else if (r & R1_ILLEGAL_COMMAND) {
    type(SD_CARD_TYPE_SD1);
  }
  else {
    error(SD_CARD_ERROR_CMD8, r);
  }
  // initialize card and send host supports SDHC if SD2
  for (uint16_t t0 = millis();;) {
    cardCommand(CMD55, 0);
    r = cardCommand(ACMD41, type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0);
    if (r == R1_READY_STATE) break;
    
    // timeout after 2 seconds
    if (((uint16_t)millis() - t0) > 2000) {
      error(SD_CARD_ERROR_ACMD41);
      return false;
    }
  }
  // if SD2 read OCR register to check for SDHC card
  if (type() == SD_CARD_TYPE_SD2) {
    if(cardCommand(CMD58, 0)) {
      error(SD_CARD_ERROR_CMD58);
      return false;
    }
    if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
    
    // discard rest of ocr
    for (uint8_t i = 0; i < 3; i++) spiRec();
  }

  // use max SPI frequency unless slow is true
  SPCR &= ~((1 << SPR1) | (1 << SPR0)); // f_OSC/4
  
  if (!slow) SPSR |= (1 << SPI2X); // Doubled Clock Frequency: f_OSC/2
  spiSSHigh();
  return true;
}
Exemplo n.º 6
0
/**
 * Initialize a SD flash memory card.
 *
 * \param[in] slow Set SPI Frequency F_CPU/4 if true else F_CPU/2.
 *
 * \return The value one, true, is returned for success and
 * the value zero, false, is returned for failure. 
 */  
uint8_t Sd2Card::init(uint8_t slow)
{
  uint8_t r;
  errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;

  // set pin modes
  spiSSOutputMode();
  spiSSHigh();
  spiMISOInputMode();
  spiMOSIOutputMode();
  spiSCKOutputMode();
  
#ifndef SOFTWARE_SPI
  //Enable SPI, Master, clock rate f_osc/128
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
#endif //SOFTWARE_SPI

  //must supply min of 74 clock cycles with CS high.
  for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
  
  // next two lines prevent re-init hang by cards that were in partial read
  spiSSLow();
  for (uint16_t i = 0; i <= 512; i++) spiRec();
  
  // command to go idle in SPI mode
  for (uint8_t retry = 0; ; retry++) {
    if ((r = cardCommand(CMD0, 0)) ==  R1_IDLE_STATE) break;
    if (retry == 10) {
      error(SD_CARD_ERROR_CMD0, r);
      return false;
    }
  }
  // check SD version
  if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
    type(SD_CARD_TYPE_SD1);
  }
  else {
    // only need last byte of r7 response
    for(uint8_t i = 0; i < 4; i++) r = spiRec();
    if (r != 0XAA) {
      error(SD_CARD_ERROR_CMD8, r);
      return false;
    }
    type(SD_CARD_TYPE_SD2);
  }
  // initialize card and send host supports SDHC if SD2
  for (uint16_t t0 = millis();;) {
    r = cardAcmd(ACMD41, type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0);
    if (r == R1_READY_STATE) break;
    // timeout after 2 seconds
    if (((uint16_t)millis() - t0) > 2000) {
      error(SD_CARD_ERROR_ACMD41);
      return false;
    }
  }
  // if SD2 read OCR register to check for SDHC card
  if (type() == SD_CARD_TYPE_SD2) {
    if(cardCommand(CMD58, 0)) {
      error(SD_CARD_ERROR_CMD58);
      return false;
    }
    if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
    // discard rest of ocr 
    for (uint8_t i = 0; i < 3; i++) spiRec();
  }
#ifndef SOFTWARE_SPI
  // set SPI frequency to f_OSC/4
  SPCR &= ~((1 << SPR1) | (1 << SPR0));
  // if !slow set SPI frequency to f_OSC/2
  if (!slow) SPSR |= (1 << SPI2X); 
#endif // SOFTWARE_SPI

  spiSSHigh();
  return true;
}