Example #1
0
// read a size Byte big block beginning at the address.
char mmcReadBlock(const unsigned long address, const unsigned long count, unsigned char *pBuffer) {
  char rvalue = MMC_RESPONSE_ERROR;

  // Set the block length to read
  if (mmcSetBlockLength (count) == MMC_SUCCESS) {   // Attempt to set block length
    MMC_CS_LOW ();
    // send read command MMC_READ_SINGLE_BLOCK=CMD17
    mmcSendCmd (MMC_READ_SINGLE_BLOCK,address, 0xFF);
    // Send 8 Clock pulses of delay, check if the MMC acknowledged the read block command
    // it will do this by sending an affirmative response
    // in the R1 format (0x00 is no errors)
    if (mmcGetResponse() == 0x00) {
      // Look for the data token to signify the start of data
      if (mmcGetXXResponse(MMC_START_DATA_BLOCK_TOKEN) == MMC_START_DATA_BLOCK_TOKEN) {
        // Clock the actual data transfer and receive the bytes; spi_read automatically finds the Data Block
        spiReadFrame(pBuffer, count);
        // Get CRC bytes (not really needed by us, but required by MMC)
        spiSendByte(DUMMY_CHAR);
        spiSendByte(DUMMY_CHAR);
        rvalue = MMC_SUCCESS;
      }
      else { // The data token was never received
        rvalue = MMC_DATA_TOKEN_ERROR;      // 3
      }
    }
    else {   // The MMC never acknowledge the read command
      rvalue = MMC_RESPONSE_ERROR;          // 2
    }
  }
  else {	// The block length was not set correctly
    rvalue = MMC_BLOCK_SET_ERROR;           // 1
  }
  MMC_CS_HIGH ();
  spiSendByte(DUMMY_CHAR);
  return rvalue;
}// mmc_read_block
void main(void) {
	//Turn off the watchdog timer
	WDTCTL = WDTPW + WDTHOLD;

	P1DIR |= LED;
	P1OUT &= ~LED;

	//16MHz
	//Set DCO to 16 MHz calibrated
	DCOCTL = CALDCO_16MHZ;
	BCSCTL1 = CALBC1_16MHZ;

	//Reset SD card by cycling power
	//Credit to Boris Cherkasskiy and his blog post on Launchpad+MMC
	P2DIR |= BIT2;
	P2OUT &= ~BIT2;
	__delay_cycles(1600000);	// 100ms @ 16MHz
	P2OUT |= BIT2;
	__delay_cycles(1600000);	// 100ms @ 16MHz

	//Initialize MMC library
	while (MMC_SUCCESS != mmcInit());
	//Verify card ready
	while (MMC_SUCCESS != mmcPing());
	//Check the memory card size
	volatile unsigned long size = mmcReadCardSize();

	//Toggle the LED to indicate that reading was successful
	P1OUT ^= LED;

	//Test that the SD card is working
	//Read in the OEM name and version in bytes 3-10
	volatile unsigned char block[64] = {0};

	// Read in a 512 byte sector
	// This is a multipart process.
	// First you must mount the block, telling the SD card the relative offset
	// of your subsequent reads. Then you read the block in multiple frames.
	// We do this so we don't need to allocate a full 512 byte buffer in the
	// MSP430's memory. Instead we'll use smaller 64 byte buffers. This
	// means that an entire block will take 8 reads. The spiReadFrame command
	// reads in the given number of bytes into the byte array passed to it.
	// After reading all of the data in the block it should be unmounted.
	//volatile char result = mmcReadBlock(0, 64, block);
	//volatile char result = mmcMountBlock(0, 512);
	volatile char result = mmcMountBlock(0, 512);

	//My FAT partition apparently starts at block 129 (0x81)
	//If you have a FAT16 filesystem you could read data from that point
	//Read in the block 64 bytes at a time
	if (result == MMC_SUCCESS) {
		volatile int i = 0;
		//8 blocks of 64 to read
		for (i = 0; i < 8; ++i) {
			//If you set a breakpoint here you can examine the memory in the card.
			spiReadFrame((void*)block, 64);
		}
		mmcUnmountBlock();
	}

	while (1);
}