/**
 * 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.º 2
0
/**
 * Writes a 512 byte block to a SD card.
 *
 * \param[in] blockNumber Logical block to be written.
 * \param[in] src Pointer to the location of the data to be written.
 * \return The value one, true, is returned for success and
 * the value zero, false, is returned for failure.
 */
uint8_t Sd2Card::writeBlock(uint32_t blockNumber, uint8_t *src)
{
#if SD_PROTECT_BLOCK_ZERO
  //don't allow write to first block
  if (blockNumber == 0) {
    error(SD_CARD_ERROR_WRITE_BLOCK_ZERO);
    return false;
  }
#endif //SD_PROTECT_BLOCK_ZERO

  //use address if not SDHC card
  if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
  if (cardCommand(CMD24, blockNumber)) {
    error(SD_CARD_ERROR_CMD24);
    return false;
  }
  if(!writeData(DATA_START_BLOCK, src)) return false;
  
  // wait for flash programming to complete
  if (!waitWriteDone()) return false;
  
  // response is r2 so get and check byte two for nonzero
  if (cardCommand(CMD13, 0) || spiRec()) {
    error(SD_CARD_ERROR_WRITE_PROGRAMMING);
    return false;
  }
  spiSSHigh();
  return true;
}
uint8_t SdCard::readReg(uint8_t cmd, uint8_t *dst)
{
  if (cardCommand(cmd, 0)) {
    spiSSHigh();
    return false;
  }
  return readTransfer(dst, 16);
}
Exemplo n.º 4
0
/** End a write multiple blocks sequence. 
 *
* \return The value one, true, is returned for success and
 * the value zero, false, is returned for failure.
 */
uint8_t Sd2Card::writeStop(void)
{
  if (!waitWriteDone()) return false;
  spiSend(STOP_TRAN_TOKEN);
  if (!waitWriteDone()) return false;
  spiSSHigh();
  return true;
}
Exemplo n.º 5
0
/** Skip remaining data in a block when in partial block read mode. */
void SdReader::readEnd(void) {
  if (inBlock_) {
    // skip data and crc
    SPDR = 0XFF;
    while (offset_++ < 513) {
      while(!(SPSR & (1 << SPIF)));
      SPDR = 0XFF;
    }
    // wait for last crc byte
    while(!(SPSR & (1 << SPIF)));
    spiSSHigh();
    inBlock_ = 0;
  }
}
Exemplo n.º 6
0
/** read CID or CSR register */
uint8_t Sd2Card::readRegister(uint8_t cmd, uint8_t *dst)
{
  if (cardCommand(cmd, 0)) {
    error(SD_CARD_ERROR_READ_REG);
    return false;
  }
  if(!waitStartBlock()) return false;
  //transfer data
  for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec();
  spiRec();// get first crc byte
  spiRec();// get second crc byte
  spiSSHigh();
  return true;
}
Exemplo n.º 7
0
/** read CID or CSR register */
uint8_t sdReadRegister(uint8_t cmd, uint8_t *dst) {
   uint16_t i;
   if (sdCardCommand(cmd, 0)) {
      error1(SD_CARD_ERROR_READ_REG);
      return 0;
   }
   if(!sdWaitStartBlock()) return 0;

   //transfer data
   for (i = 0; i < 16; i++) dst[i] = spiRec();

   spiRec();// get first crc byte
   spiRec();// get second crc byte

   spiSSHigh();
   return 1;
}
//------------------------------------------------------------------------------
uint8_t SdCard::readTransfer(uint8_t *dst, uint16_t count)
{
  //wait for start of data
  for (uint16_t retry = 0; spiRec() != DATA_START_BLOCK; retry++) {
    if (retry == 0XFFFF) {
      error(SD_ERROR_READ_TIMEOUT);
      return false;
    }
  }
  //start first spi transfer
  SPDR = 0XFF;
  for (uint16_t i = 0; i < count; i++) {
    while(!(SPSR & (1 << SPIF)));
    dst[i] = SPDR;
    SPDR = 0XFF;  
  }
  // wait for first CRC byte
  while(!(SPSR & (1 << SPIF)));  
  spiRec();//second CRC byte
  spiSSHigh();
  return true;
}
/**
 * Writes a 512 byte block to a storage device.
 *  
 * \param[in] blockNumber Logical block to be written.
 * \param[in] src Pointer to the location of the data to be written. 
 * \return The value one, true, is returned for success and
 * the value zero, false, is returned for failure.      
 */   
uint8_t SdCard::writeBlock(uint32_t blockNumber, uint8_t *src)
{
  uint32_t address = blockNumber << 9;
#if SD_PROTECT_BLOCK_ZERO
  //don't allow write to first block
  if (address == 0) {
    error(SD_ERROR_BLOCK_ZERO_WRITE);
    return false;
  }
#endif //SD_PROTECT_BLOCK_ZERO
  if (cardCommand(CMD24, address)) {
    error(SD_ERROR_CMD24);
    return false;
  }
  // optimize write loop
  SPDR = DATA_START_BLOCK;
  for (uint16_t i = 0; i < 512; i++) {
    while(!(SPSR & (1 << SPIF)));
    SPDR = src[i];
  }
  while(!(SPSR & (1 << SPIF)));// wait for last data byte
  spiSend(0xFF);// dummy crc
  spiSend(0xFF);// dummy crc
  uint8_t r1 = spiRec();
  if ((r1 & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
    error(SD_ERROR_WRITE_RESPONSE, r1);
    return false;
  }
  // wait for card to complete write programming
  for (uint16_t retry = 0; spiRec() != 0XFF ; retry++) {
    if (retry == 0XFFFF) {
      error(SD_ERROR_WRITE_TIMEOUT);
      return false;
    }
  }
  spiSSHigh();
  return true;
}
Exemplo n.º 10
0
/** Skip remaining data in a block when in partial block read mode. */
void Sd2Card::readEnd(void)
{
  if (inBlock_) {
      // skip data and crc
#ifdef OPTIMIZE_HARDWARE_SPI

    // optimize skip for hardware
    SPDR = 0XFF;
    while (offset_++ < 513) {
      while(!(SPSR & (1 << SPIF)));
      SPDR = 0XFF;
    }
    // wait for last crc byte
    while(!(SPSR & (1 << SPIF)));
    
#else // OPTIMIZE_HARDWARE_SPI

    while (offset_++ < 514) spiRec();
#endif // OPTIMIZE_HARDWARE_SPI

    spiSSHigh();
    inBlock_ = 0;
  }
}
Exemplo n.º 11
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;
}
//------------------------------------------------------------------------------
void SdCard::error(uint8_t code) 
{
  errorCode = code; 
  spiSSHigh();
}
Exemplo n.º 13
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;
}