Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Thread

What are the main differences between interfacing with SD and MMC devices?

What are the main differences between interfacing with SD and MMC devices?

2006-04-12 by darcy_will

Hi all,

Please excuse my ignorance of these issues.  I'm only just looking 
to begin playing with an Olimex LPC2148 dev kit having finally got 
the thing up and running with GCC/Insight etc...

Because the development board comes with an MMC (and SD?) slot I 
just assumed this is probably the type of flash device I'd end up 
using in our "product" (just a home project at the moment).  Having 
had a bit of a look around it's fairly easy to see that SD has 
overtaken MMC as far as price and availability go.  This certainly 
makes me think that SD is the flash type to go with.

If a FAT16/32 file system is implemented on this kit (using 
something like RDCF or EFSL for example), how easy is it to swap the 
flash cards between MMC and SD?  I've seen that SD and MMC can both 
use the same transfer protocol to the uC, but does the change in 
format also require an overhaul of the flash driver on the uC?

This is kind of a dual purpose question...  
a) Can the same driver used for MMC cards be used for SD?
b) if not, how different is the interface?

I'm not looking to be able to use both types of flash cards on the 
same project...  more curious as which is the one to go with.

There certainly *seem* to be more examples out there for MMC than 
SD...  In fact I haven't found any examples of SD file systems on 
the LPC21xx range.  Maybe I'm just not looking hard enough?  :)

Any help would be greatly appreciated!

Cheers
Darcy

Re: [lpc2000] What are the main differences between interfacing with SD and MMC devices?

2006-04-12 by ippogrifo66@hotmail.com

Sorry, what is RDCF ?

Pier
Show quoted textHide quoted text
  ----- Original Message ----- 
  From: darcy_will 
  To: lpc2000@yahoogroups.com 
  Sent: Wednesday, April 12, 2006 11:59 AM
  Subject: [lpc2000] What are the main differences between interfacing with SD and MMC devices?


  Hi all,

  Please excuse my ignorance of these issues.  I'm only just looking 
  to begin playing with an Olimex LPC2148 dev kit having finally got 
  the thing up and running with GCC/Insight etc...

  Because the development board comes with an MMC (and SD?) slot I 
  just assumed this is probably the type of flash device I'd end up 
  using in our "product" (just a home project at the moment).  Having 
  had a bit of a look around it's fairly easy to see that SD has 
  overtaken MMC as far as price and availability go.  This certainly 
  makes me think that SD is the flash type to go with.

  If a FAT16/32 file system is implemented on this kit (using 
  something like RDCF or EFSL for example), how easy is it to swap the 
  flash cards between MMC and SD?  I've seen that SD and MMC can both 
  use the same transfer protocol to the uC, but does the change in 
  format also require an overhaul of the flash driver on the uC?

  This is kind of a dual purpose question...  
  a) Can the same driver used for MMC cards be used for SD?
  b) if not, how different is the interface?

  I'm not looking to be able to use both types of flash cards on the 
  same project...  more curious as which is the one to go with.

  There certainly *seem* to be more examples out there for MMC than 
  SD...  In fact I haven't found any examples of SD file systems on 
  the LPC21xx range.  Maybe I'm just not looking hard enough?  :)

  Any help would be greatly appreciated!

  Cheers
  Darcy






------------------------------------------------------------------------------
  YAHOO! GROUPS LINKS 

    a..  Visit your group "lpc2000" on the web.
      
    b..  To unsubscribe from this group, send an email to:
     lpc2000-unsubscribe@yahoogroups.com
      
    c..  Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service. 


------------------------------------------------------------------------------



[Non-text portions of this message have been removed]

Re: [lpc2000] What are the main differences between interfacing with SD and MMC devices?

2006-04-12 by Mukund Deshmukh

>   Because the development board comes with an MMC (and SD?) slot I
>   just assumed this is probably the type of flash device I'd end up
>   using in our "product" (just a home project at the moment).  Having
>   had a bit of a look around it's fairly easy to see that SD has
>   overtaken MMC as far as price and availability go.  This certainly

On the same board I have run EFSL with MMC card, although EFSL says SD card,
so in think SD and MMC interchangeable.

Best Regards,

Mukund Deshmukh.
Beta Computronics Pvt Ltd
10/1, IT Park, Parsodi,
Nagpur-440022
Cell - 9422113746

Re: What are the main differences between interfacing with SD and MMC devices?

2006-04-12 by derbaier

--- In lpc2000@yahoogroups.com, "darcy_will" <darcyw@...> wrote:

> 
> This is kind of a dual purpose question...  
> a) Can the same driver used for MMC cards be used for SD?
> b) if not, how different is the interface?
> 

SD is a superset of MMC, and it includes the MMC commands as a subset.
So, if you just use the MMC subset with the SPI interface you should
be able to use SD and MMC interchangeably. I have been doing just that
with code based on the Circuit Cellar FAT drivers.

-- Dave

Re: [lpc2000] What are the main differences between interfacing with SD and MMC devices?

2006-04-12 by Tom Walsh

ippogrifo66@... wrote:

>Sorry, what is RDCF ?
>
>  
>
http://www.openhardware.net/?title=RDCF2%20DOS%20FAT%20Filesystem%20for%20LPC2138&dir=rdcf2&file=rdcf2lpc2138.html


-- 
Tom Walsh - WN3L - Embedded Systems Consultant
http://openhardware.net, http://cyberiansoftware.com
"Windows? No thanks, I have work to do..."
----------------------------------------------------

Re: [lpc2000] What are the main differences between interfacing with SD and MMC devices?

2006-04-12 by Bertrik Sikken

darcy_will wrote:
> Hi all,
> 
> Please excuse my ignorance of these issues.  I'm only just looking 
> to begin playing with an Olimex LPC2148 dev kit having finally got 
> the thing up and running with GCC/Insight etc...
> 
> Because the development board comes with an MMC (and SD?) slot I 
> just assumed this is probably the type of flash device I'd end up 
> using in our "product" (just a home project at the moment).  Having 
> had a bit of a look around it's fairly easy to see that SD has 
> overtaken MMC as far as price and availability go.  This certainly 
> makes me think that SD is the flash type to go with.
> 
> If a FAT16/32 file system is implemented on this kit (using 
> something like RDCF or EFSL for example), how easy is it to swap the 
> flash cards between MMC and SD?  I've seen that SD and MMC can both 
> use the same transfer protocol to the uC, but does the change in 
> format also require an overhaul of the flash driver on the uC?
>
> This is kind of a dual purpose question...  
> a) Can the same driver used for MMC cards be used for SD?
> b) if not, how different is the interface?

In an SD card product manual that I have, it is mentioned that
MMC cards should not be clocked faster than 400 kHz during
initialisation.

Also I've seen it mentioned in example code that MMC cards
first need at least 80 clocks without being selected during
startup. Not sure if this is MMC specific though.

So, yes, you should be able to use the same driver (a SPI mode
driver), provided that you do the 400 kHz thing (and possibly
also the 80 clocks).

Physically, an SD card is thicker than a MMC card, so an
MMC card will fit in a SD slot, but not the other way around.

> I'm not looking to be able to use both types of flash cards on the 
> same project...  more curious as which is the one to go with.

I would go for SD card, it's more modern and also cheaper.

> There certainly *seem* to be more examples out there for MMC than 
> SD...  In fact I haven't found any examples of SD file systems on 
> the LPC21xx range.  Maybe I'm just not looking hard enough?  :)

As far as I know, the official SD/MMC specification is not public,
that probably explains a lot.

> Any help would be greatly appreciated!

Regards,
Bertrik

Re: What are the main differences between interfacing with SD and MMC devices?

2006-04-12 by rtstofer

> As far as I know, the official SD/MMC specification is not public,
> that probably explains a lot.
> 
> > Any help would be greatly appreciated!
> 
> Regards,
> Bertrik
>

There are several documents at SanDisk that will help.  However, the
'official' SD spec is not among them.  The group that owns the spec
wants to sell, not give away.

However, the complete MMC spec is available.

Richard

Re: [lpc2000] SD/SPI driver code

2006-04-12 by Clyde Stubbs

Attached is some code for driving an SD card via an SPI port. This
was written specifically for a SiLabs C8051F320 but should adapt
with little trouble to any other SPI interface.

The code has been widely tested on a variety of different brand SD
cards - some have little quirks.

Clyde


On Wed, Apr 12, 2006 at 07:16:32PM -0000, darcy_will wrote:
> Thanks to everyone that has offered their help with this topic!  I 
> honestly didn't expect such a fantastic response in such a short 
> period of time.
> 
> Cheers all
> D.
> 
> 
> 
> 
> 
>  
> Yahoo! Groups Links
> 
> 
> 
>  
> 

-- 
Clyde Stubbs                     |            HI-TECH Software
Email: clyde@...          |          Phone            Fax
WWW:   http://www.htsoft.com/    | USA: (408) 490 2885  (408) 490 2885
PGP:   finger clyde@...   | AUS: +61 7 3722 7777 +61 7 3722 7778
---------------------------------------------------------------------------
HI-TECH C: compiling the real world.

  ----------

/* SD card interface. Copyright (C) 2005 HI-TECH Software Pty. Ltd. */

#include	<8051.h>

#define	FALSE	0
#define	TRUE	1

// Error codes for the SD

enum {
	RESET_FAIL=1, READ_FAIL, CSD_FAIL, WRITE_FAIL, STATUS_FAIL, ACMD_FAIL, ERASE_FAIL
};


// card present states

enum {
	CARD_MISSING = 0,
	CARD_PRESENT,
	CARD_READY,
	CARD_FAIL,
	CARD_EJECTED
}	card_state;

static unsigned char 		*	xptr;		// data pointer
static unsigned char 			error_code;	// code d'error
static unsigned long			card_size;	// card size in blocks
static unsigned long			part_offset;// offset to start of first partition
static unsigned char			file_format;	// partition layout

#define	V33			(1<< 6)		// bit identifying 3.3V
#define	SD_BLKLEN	512			// block size
#define	CSD_SIZE	16			// CSD size in bytes
#define	CID_SIZE	16			// CID size in bytes


unsigned char blkbuf[SD_BLKLEN];



#define	ACMD	55			// command following is application specific
#define	CARD_SELECT		(P1_BITS.B3)		// this bit should drive the card select
#define	SPIBUSY	0x80	// spi busy bit
#define	CRC				0x95		// all purpose CRC

static bit				fat32;			// set if we have a fat32 card
static bit				fat_check;		// we need to check the fat again
static unsigned char	timeout;		// timeout value in ticks

// this must be implemented in an timer interrupt. If timeout is non-zero, the
// interrupt routine should decrement it once per timer tick.
// adjust the calculation in SET_TIMEOUT so that the argument represents milliseconds.

#define	SET_TIMEOUT(x)	(timeout = (((x)*128UL))/1000+1)
#define	TIMEDOUT()		(timeout == 0)

// fetch a long value from the buffer

static unsigned long
get_long(unsigned char * ptr)
{
	unsigned long	value;

	value = *ptr++;
	value += *ptr++ << 8;
	value += (unsigned long)*ptr++ << 16;
	value += (unsigned long)*ptr++ << 24;
	return value;
}

static void
SPI_init(void)
{
	// setup the SPI for the SD card. 
	// Data latched on rising edge, input valid in middle of clock,
	// idle state is high.
	// initial clock for the SD card must be very slow - 200kHz
	// due to the open-drain connection

	SPI0CKR = 0x30;				// start SPI real slow
	SPI0CFG = 0B01000000;
	SPI0CN = 1;
}

// Send one byte to the SPI

static void
SPI_send(unsigned char databyte)
{
	while(TXBMT == 0)
		continue;
	SPI0DAT = databyte;
}

// read one byte from the SPI

static unsigned char
SPI_read(void)
{
	SPIF = 0;
	SPI0DAT = 0xFF;		// clock out 1s while clocking in data
	while(!SPIF)
		continue;
	return SPI0DAT;
}

// Send idle (0xFF) a specified number of bytes

static void
SD_idle(unsigned char cnt)
{
	while(cnt--)
		SPI_send(0xFF);
}

// Send a command and wait for a response

static unsigned char
SD_send(unsigned char cmd, unsigned long arg)
{
	unsigned char	tok;

	CARD_SELECT = 0;			// select the card
	SD_idle(3);				// lead-in
	SPI_send(cmd|0x40);			// send the command
	SPI_send(arg >> 24);
	SPI_send(arg >> 16);
	SPI_send(arg >> 8);
	SPI_send(arg);
	SPI_send(CRC);
	cmd = 16;
	do
		tok = SPI_read();	// wait for response - up to 16 times
	while(tok & 0x80 && --cmd != 0);
	return tok;
}

static bit
SD_reset(void)
{
	SPI_init();
	SD_idle(100);
	CARD_SELECT = 0;		// select the card
	SD_idle(100);			// send numerous clocks to initialize
	CARD_SELECT = 1;
	SD_idle(100);
	SD_send(0, 0);			// send initialization command
	SET_TIMEOUT(1000);		// initialization should take no more than 1 second
	do {
		if(TIMEDOUT()) {
			error_code = RESET_FAIL;
			return FALSE;
		}
		SD_send(55, 0);			// app-specific command follows
	} while(SD_send(41, 0) & 1);
	SPI0CKR = 0;				// set SPI to maximum speed - 12 MHz
	return TRUE;
}


static unsigned char
SD_cmd(unsigned char cmd, unsigned long arg)
{
	if(SD_send(cmd, arg) == 0)
		return 0;
	// card did not respond in a reasonable time - might be a PNY!
	// hard reset the card and retry the command, but only once.
	_delay(24000000/4);		// wait 240 ms to ensure buffers flushed
	SD_reset();
	return SD_send(cmd, arg);
}

// read the status register

static unsigned
SD_readstatus(void)
{
	unsigned char	i;

	i = SD_cmd(13, 0);
	if(i & 0x80) {
		error_code = STATUS_FAIL;
		return FALSE;
	}
	return (i << 8) + SPI_read();
}

// read the CSD - 16 bytes 

static bit
SD_readcsd(void)
{
	unsigned char	token;
	unsigned char	i;
	unsigned int	len;

	if(SD_cmd(9, 0)) {
		error_code = CSD_FAIL;
		return FALSE;
	}
	SET_TIMEOUT(200);
	do
		token = SPI_read();
	while(token != 0xFE && !TIMEDOUT());
	if(token & 1) {
		error_code = CSD_FAIL;
		return FALSE;
	}
	i = 0;
	do
		blkbuf[i] = SPI_read();
	while(++i != CSD_SIZE);
	SPI_read();
	SPI_read();
	i = (blkbuf[15-6] & 3) << 1;		// bits 48-49
	i += blkbuf[15-5] >> 7;			// bit 47
	i += 2;
	len = blkbuf[15-8] << 2;
	len += blkbuf[15-7] >> 6;
	len += (blkbuf[15-9] & 3) << 10;
	len++;
	card_size = (1L << i) * len - 1;	// set to number of last block
	file_format = (blkbuf[15-1] >> 2) & 3;
	return TRUE;
}

static void
SD_stopwrite(void)
{
	SPI_send(0xFD);
	SET_TIMEOUT(500);
	SPI_send(0xFF);
	while(!TIMEDOUT())
		if(SPI_read() == 0xFF)
			break;
}

// commence a read operation

static bit
SD_startread(unsigned long blockno)
{
	if(SD_cmd(17, blockno << 9)) {
		error_code = READ_FAIL;
		return FALSE;
	}
	return TRUE;
}

static bit
SD_waitread(void)
{
	unsigned char	token;
	unsigned int	i;

	SET_TIMEOUT(200);
	do
		token = SPI_read();
	while(token != 0xFE && !TIMEDOUT());
	if(token & 1) {
		error_code = READ_FAIL;
		return FALSE;
	}
	return TRUE;
}

// commence a write operation

static bit
SD_startwrite(unsigned long blockno)
{
	unsigned char	token;
	unsigned int	i;

	if(SD_cmd(24, blockno << 9)) {
		error_code = WRITE_FAIL;
		return FALSE;
	}
	SPI_send(0xFF);
	SPI_send(0xFE);			// start of write
	return TRUE;
}

static bit
SD_writeblock(unsigned long blockno, unsigned char * buf)
{
	unsigned int	i;
	unsigned char	tok;

	if(!SD_startwrite(blockno))
		return FALSE;
	i = SD_BLKLEN;
	do
		SPI_send(*buf++);
	while(--i != 0);
	do
		tok = SPI_read();
	while(tok == 0xFF);
	tok &= 0x1F;
	if(tok != 5) {
		error_code = WRITE_FAIL;
		return FALSE;
	}
	// wait for completion
	while(SPI_read() != 0xFF)
		continue;
	return TRUE;
}

// read one BLKLEN block from the card.

static bit
SD_readblock(unsigned long blockno, unsigned char * buf)
{
	unsigned int	i;

	if(!SD_startread(blockno))
		return FALSE;
	if(!SD_waitread())
		return FALSE;
	i = 0;
	do
		*buf++ = SPI_read();
	while(++i != SD_BLKLEN);
	SPI_read();
	SPI_read();		// flush unwanted CRC
	return TRUE;
}


// init the SD card
static bit
SD_init(void)
{
	unsigned char	i;
	unsigned long	sectors;

	part_offset = 0;
	card_size = 0;

	if(!SD_reset() || !SD_readcsd())
		return FALSE;
	if(file_format == 0) {
		if(!SD_readblock(0, blkbuf))
			return FALSE;
		if(blkbuf[SD_BLKLEN-1] == 0xAA && blkbuf[SD_BLKLEN-2] == 0x55) {
			xptr = blkbuf+0x1BE;		// point to start of partition table
			i = 4;
			do {
				if(xptr[0] == 0 &&
						(xptr[4] == 1 || xptr[4] == 4 || xptr[4] == 6 || xptr[4] == 14)) {
					part_offset = get_long(xptr+8);
					card_size -= part_offset;
					break;
				}
			} while(--i != 0);
		}
	}
	return TRUE;
}

// check the filesystem type - set a flag if it is FAT32
static void
SD_fatchick(void)
{
	unsigned char	i;
	unsigned long	sectors;

	fat32 = 0;
	fat_check = 0;
	if(!SD_readblock(part_offset, blkbuf))
		return;
	if(blkbuf[0x13] != 0 || blkbuf[0x14] != 0)
		return;								// must be <= 32MB, quite safe
	sectors = get_long(blkbuf+0x20);		// get number of sectors
	i = blkbuf[0x0D];						// sectors per cluster
	while((i >>= 1) != 0)
		sectors >>= 1;
	if(sectors >= 65525)
		fat32 = 1;
}




[Non-text portions of this message have been removed]

Re: [lpc2000] What are the main differences between interfacing with SD and MMC devices?

2006-04-12 by Clyde Stubbs

On Wed, Apr 12, 2006 at 02:08:28PM -0600, Michael Anton wrote:
> Most of the implementations you will find for SD actually implement
> the MMC single bit communication method rather than the 4 bit wide
> mode of SD.  This is because the specification for SD is not open
> to the public, and the implementation of it requires a yearly

This isn't the only reason - the 4 bit mode requires that a CRC be
calculated on each bit - i.e. 4 CRCs in parallel. The SPI mode can
be used without CRC, or with only one CRC for the whole
data stream. This makes the 4 bit mode unattractive to implement on
general purpose micros (whereas in a custom ASIC the 4 CRCs are no
big deal).

> may work with MMC cards as well.  But, I think I saw a mention
> somewhere (perhaps on the SanDisk site) that the initialization
> sequence for MMC and SD is slightly different.

It is, but the reduced clock rate is still required, since the SD
card also initializes in an open-drain mode.

The freely available Sandisk documentation is sufficient to implement
SD communication in either mode, without buying the official SD
spec.

Clyde


-- 
Clyde Stubbs                     |            HI-TECH Software
Email: clyde@...          |          Phone            Fax
WWW:   http://www.htsoft.com/    | USA: (408) 490 2885  (408) 490 2885
PGP:   finger clyde@...   | AUS: +61 7 3722 7777 +61 7 3722 7778
---------------------------------------------------------------------------
HI-TECH C: compiling the real world.

Re: [lpc2000] SD/SPI driver code

2006-04-12 by Clyde Stubbs

Ok, seems the attachment was stripped. It's here:

http://www.htsoft.com/resources/sd.c

Clyde

On Thu, Apr 13, 2006 at 05:51:01AM +1000, Clyde Stubbs wrote:
> Attached is some code for driving an SD card via an SPI port. This
> was written specifically for a SiLabs C8051F320 but should adapt
> with little trouble to any other SPI interface.
> 
> The code has been widely tested on a variety of different brand SD
> cards - some have little quirks.
> 
> Clyde
> 
> 
> On Wed, Apr 12, 2006 at 07:16:32PM -0000, darcy_will wrote:
> > Thanks to everyone that has offered their help with this topic!  I 
> > honestly didn't expect such a fantastic response in such a short 
> > period of time.
> > 
> > Cheers all
> > D.
> > 
> > 
> > 
> > 
> > 
> >  
> > Yahoo! Groups Links
> > 
> > 
> > 
> >  
> > 
> 
> -- 
> Clyde Stubbs                     |            HI-TECH Software
> Email: clyde@...          |          Phone            Fax
> WWW:   http://www.htsoft.com/    | USA: (408) 490 2885  (408) 490 2885
> PGP:   finger clyde@...   | AUS: +61 7 3722 7777 +61 7 3722 7778
> ---------------------------------------------------------------------------
> HI-TECH C: compiling the real world.
> 
>   ----------
> 
> /* SD card interface. Copyright (C) 2005 HI-TECH Software Pty. Ltd. */
> 
> #include	<8051.h>
> 
> #define	FALSE	0
> #define	TRUE	1
> 
> // Error codes for the SD
> 
> enum {
> 	RESET_FAIL=1, READ_FAIL, CSD_FAIL, WRITE_FAIL, STATUS_FAIL, ACMD_FAIL, ERASE_FAIL
> };
> 
> 
> // card present states
> 
> enum {
> 	CARD_MISSING = 0,
> 	CARD_PRESENT,
> 	CARD_READY,
> 	CARD_FAIL,
> 	CARD_EJECTED
> }	card_state;
> 
> static unsigned char 		*	xptr;		// data pointer
> static unsigned char 			error_code;	// code d'error
> static unsigned long			card_size;	// card size in blocks
> static unsigned long			part_offset;// offset to start of first partition
> static unsigned char			file_format;	// partition layout
> 
> #define	V33			(1<< 6)		// bit identifying 3.3V
> #define	SD_BLKLEN	512			// block size
> #define	CSD_SIZE	16			// CSD size in bytes
> #define	CID_SIZE	16			// CID size in bytes
> 
> 
> unsigned char blkbuf[SD_BLKLEN];
> 
> 
> 
> #define	ACMD	55			// command following is application specific
> #define	CARD_SELECT		(P1_BITS.B3)		// this bit should drive the card select
> #define	SPIBUSY	0x80	// spi busy bit
> #define	CRC				0x95		// all purpose CRC
> 
> static bit				fat32;			// set if we have a fat32 card
> static bit				fat_check;		// we need to check the fat again
> static unsigned char	timeout;		// timeout value in ticks
> 
> // this must be implemented in an timer interrupt. If timeout is non-zero, the
> // interrupt routine should decrement it once per timer tick.
> // adjust the calculation in SET_TIMEOUT so that the argument represents milliseconds.
> 
> #define	SET_TIMEOUT(x)	(timeout = (((x)*128UL))/1000+1)
> #define	TIMEDOUT()		(timeout == 0)
> 
> // fetch a long value from the buffer
> 
> static unsigned long
> get_long(unsigned char * ptr)
> {
> 	unsigned long	value;
> 
> 	value = *ptr++;
> 	value += *ptr++ << 8;
> 	value += (unsigned long)*ptr++ << 16;
> 	value += (unsigned long)*ptr++ << 24;
> 	return value;
> }
> 
> static void
> SPI_init(void)
> {
> 	// setup the SPI for the SD card. 
> 	// Data latched on rising edge, input valid in middle of clock,
> 	// idle state is high.
> 	// initial clock for the SD card must be very slow - 200kHz
> 	// due to the open-drain connection
> 
> 	SPI0CKR = 0x30;				// start SPI real slow
> 	SPI0CFG = 0B01000000;
> 	SPI0CN = 1;
> }
> 
> // Send one byte to the SPI
> 
> static void
> SPI_send(unsigned char databyte)
> {
> 	while(TXBMT == 0)
> 		continue;
> 	SPI0DAT = databyte;
> }
> 
> // read one byte from the SPI
> 
> static unsigned char
> SPI_read(void)
> {
> 	SPIF = 0;
> 	SPI0DAT = 0xFF;		// clock out 1s while clocking in data
> 	while(!SPIF)
> 		continue;
> 	return SPI0DAT;
> }
> 
> // Send idle (0xFF) a specified number of bytes
> 
> static void
> SD_idle(unsigned char cnt)
> {
> 	while(cnt--)
> 		SPI_send(0xFF);
> }
> 
> // Send a command and wait for a response
> 
> static unsigned char
> SD_send(unsigned char cmd, unsigned long arg)
> {
> 	unsigned char	tok;
> 
> 	CARD_SELECT = 0;			// select the card
> 	SD_idle(3);				// lead-in
> 	SPI_send(cmd|0x40);			// send the command
> 	SPI_send(arg >> 24);
> 	SPI_send(arg >> 16);
> 	SPI_send(arg >> 8);
> 	SPI_send(arg);
> 	SPI_send(CRC);
> 	cmd = 16;
> 	do
> 		tok = SPI_read();	// wait for response - up to 16 times
> 	while(tok & 0x80 && --cmd != 0);
> 	return tok;
> }
> 
> static bit
> SD_reset(void)
> {
> 	SPI_init();
> 	SD_idle(100);
> 	CARD_SELECT = 0;		// select the card
> 	SD_idle(100);			// send numerous clocks to initialize
> 	CARD_SELECT = 1;
> 	SD_idle(100);
> 	SD_send(0, 0);			// send initialization command
> 	SET_TIMEOUT(1000);		// initialization should take no more than 1 second
> 	do {
> 		if(TIMEDOUT()) {
> 			error_code = RESET_FAIL;
> 			return FALSE;
> 		}
> 		SD_send(55, 0);			// app-specific command follows
> 	} while(SD_send(41, 0) & 1);
> 	SPI0CKR = 0;				// set SPI to maximum speed - 12 MHz
> 	return TRUE;
> }
> 
> 
> static unsigned char
> SD_cmd(unsigned char cmd, unsigned long arg)
> {
> 	if(SD_send(cmd, arg) == 0)
> 		return 0;
> 	// card did not respond in a reasonable time - might be a PNY!
> 	// hard reset the card and retry the command, but only once.
> 	_delay(24000000/4);		// wait 240 ms to ensure buffers flushed
> 	SD_reset();
> 	return SD_send(cmd, arg);
> }
> 
> // read the status register
> 
> static unsigned
> SD_readstatus(void)
> {
> 	unsigned char	i;
> 
> 	i = SD_cmd(13, 0);
> 	if(i & 0x80) {
> 		error_code = STATUS_FAIL;
> 		return FALSE;
> 	}
> 	return (i << 8) + SPI_read();
> }
> 
> // read the CSD - 16 bytes 
> 
> static bit
> SD_readcsd(void)
> {
> 	unsigned char	token;
> 	unsigned char	i;
> 	unsigned int	len;
> 
> 	if(SD_cmd(9, 0)) {
> 		error_code = CSD_FAIL;
> 		return FALSE;
> 	}
> 	SET_TIMEOUT(200);
> 	do
> 		token = SPI_read();
> 	while(token != 0xFE && !TIMEDOUT());
> 	if(token & 1) {
> 		error_code = CSD_FAIL;
> 		return FALSE;
> 	}
> 	i = 0;
> 	do
> 		blkbuf[i] = SPI_read();
> 	while(++i != CSD_SIZE);
> 	SPI_read();
> 	SPI_read();
> 	i = (blkbuf[15-6] & 3) << 1;		// bits 48-49
> 	i += blkbuf[15-5] >> 7;			// bit 47
> 	i += 2;
> 	len = blkbuf[15-8] << 2;
> 	len += blkbuf[15-7] >> 6;
> 	len += (blkbuf[15-9] & 3) << 10;
> 	len++;
> 	card_size = (1L << i) * len - 1;	// set to number of last block
> 	file_format = (blkbuf[15-1] >> 2) & 3;
> 	return TRUE;
> }
> 
> static void
> SD_stopwrite(void)
> {
> 	SPI_send(0xFD);
> 	SET_TIMEOUT(500);
> 	SPI_send(0xFF);
> 	while(!TIMEDOUT())
> 		if(SPI_read() == 0xFF)
> 			break;
> }
> 
> // commence a read operation
> 
> static bit
> SD_startread(unsigned long blockno)
> {
> 	if(SD_cmd(17, blockno << 9)) {
> 		error_code = READ_FAIL;
> 		return FALSE;
> 	}
> 	return TRUE;
> }
> 
> static bit
> SD_waitread(void)
> {
> 	unsigned char	token;
> 	unsigned int	i;
> 
> 	SET_TIMEOUT(200);
> 	do
> 		token = SPI_read();
> 	while(token != 0xFE && !TIMEDOUT());
> 	if(token & 1) {
> 		error_code = READ_FAIL;
> 		return FALSE;
> 	}
> 	return TRUE;
> }
> 
> // commence a write operation
> 
> static bit
> SD_startwrite(unsigned long blockno)
> {
> 	unsigned char	token;
> 	unsigned int	i;
> 
> 	if(SD_cmd(24, blockno << 9)) {
> 		error_code = WRITE_FAIL;
> 		return FALSE;
> 	}
> 	SPI_send(0xFF);
> 	SPI_send(0xFE);			// start of write
> 	return TRUE;
> }
> 
> static bit
> SD_writeblock(unsigned long blockno, unsigned char * buf)
> {
> 	unsigned int	i;
> 	unsigned char	tok;
> 
> 	if(!SD_startwrite(blockno))
> 		return FALSE;
> 	i = SD_BLKLEN;
> 	do
> 		SPI_send(*buf++);
> 	while(--i != 0);
> 	do
> 		tok = SPI_read();
> 	while(tok == 0xFF);
> 	tok &= 0x1F;
> 	if(tok != 5) {
> 		error_code = WRITE_FAIL;
> 		return FALSE;
> 	}
> 	// wait for completion
> 	while(SPI_read() != 0xFF)
> 		continue;
> 	return TRUE;
> }
> 
> // read one BLKLEN block from the card.
> 
> static bit
> SD_readblock(unsigned long blockno, unsigned char * buf)
> {
> 	unsigned int	i;
> 
> 	if(!SD_startread(blockno))
> 		return FALSE;
> 	if(!SD_waitread())
> 		return FALSE;
> 	i = 0;
> 	do
> 		*buf++ = SPI_read();
> 	while(++i != SD_BLKLEN);
> 	SPI_read();
> 	SPI_read();		// flush unwanted CRC
> 	return TRUE;
> }
> 
> 
> // init the SD card
> static bit
> SD_init(void)
> {
> 	unsigned char	i;
> 	unsigned long	sectors;
> 
> 	part_offset = 0;
> 	card_size = 0;
> 
> 	if(!SD_reset() || !SD_readcsd())
> 		return FALSE;
> 	if(file_format == 0) {
> 		if(!SD_readblock(0, blkbuf))
> 			return FALSE;
> 		if(blkbuf[SD_BLKLEN-1] == 0xAA && blkbuf[SD_BLKLEN-2] == 0x55) {
> 			xptr = blkbuf+0x1BE;		// point to start of partition table
> 			i = 4;
> 			do {
> 				if(xptr[0] == 0 &&
> 						(xptr[4] == 1 || xptr[4] == 4 || xptr[4] == 6 || xptr[4] == 14)) {
> 					part_offset = get_long(xptr+8);
> 					card_size -= part_offset;
> 					break;
> 				}
> 			} while(--i != 0);
> 		}
> 	}
> 	return TRUE;
> }
> 
> // check the filesystem type - set a flag if it is FAT32
> static void
> SD_fatchick(void)
> {
> 	unsigned char	i;
> 	unsigned long	sectors;
> 
> 	fat32 = 0;
> 	fat_check = 0;
> 	if(!SD_readblock(part_offset, blkbuf))
> 		return;
> 	if(blkbuf[0x13] != 0 || blkbuf[0x14] != 0)
> 		return;								// must be <= 32MB, quite safe
> 	sectors = get_long(blkbuf+0x20);		// get number of sectors
> 	i = blkbuf[0x0D];						// sectors per cluster
> 	while((i >>= 1) != 0)
> 		sectors >>= 1;
> 	if(sectors >= 65525)
> 		fat32 = 1;
> }
> 
> 
> 
> 
> [Non-text portions of this message have been removed]
> 
> 
> 
>  
> Yahoo! Groups Links
> 
> 
> 
>  
> 

-- 
Clyde Stubbs                     |            HI-TECH Software
Email: clyde@...          |          Phone            Fax
WWW:   http://www.htsoft.com/    | USA: (408) 490 2885  (408) 490 2885
PGP:   finger clyde@...   | AUS: +61 7 3722 7777 +61 7 3722 7778
---------------------------------------------------------------------------
HI-TECH C: compiling the real world.

RE: [lpc2000] What are the main differences between interfacing with SD and MMC devices?

2006-04-12 by Michael Anton

> 
> If a FAT16/32 file system is implemented on this kit (using 
> something like RDCF or EFSL for example), how easy is it to swap the 
> flash cards between MMC and SD?  I've seen that SD and MMC can both 
> use the same transfer protocol to the uC, but does the change in 
> format also require an overhaul of the flash driver on the uC?
> 
> This is kind of a dual purpose question...  
> a) Can the same driver used for MMC cards be used for SD?
> b) if not, how different is the interface?
> 
> I'm not looking to be able to use both types of flash cards on the 
> same project...  more curious as which is the one to go with.
> 
> There certainly *seem* to be more examples out there for MMC than 
> SD...  In fact I haven't found any examples of SD file systems on 
> the LPC21xx range.  Maybe I'm just not looking hard enough?  :)
> 
> Any help would be greatly appreciated!
> 
> Cheers
> Darcy

Most of the implementations you will find for SD actually implement
the MMC single bit communication method rather than the 4 bit wide
mode of SD.  This is because the specification for SD is not open
to the public, and the implementation of it requires a yearly
royalty payment.  The MMC specification can be purchased, so there
has been more information available to developers.

I have used EFSL on SD, and it works well.  I have not tried a MMC
card.  EFSL does reduce the SPI clock during initialization, so it
may work with MMC cards as well.  But, I think I saw a mention
somewhere (perhaps on the SanDisk site) that the initialization
sequence for MMC and SD is slightly different.

Mike

Re: SD/SPI driver code

2006-04-12 by rtstofer

--- In lpc2000@yahoogroups.com, Clyde Stubbs <clyde@...> wrote:
>
> Ok, seems the attachment was stripped. It's here:
> 
> http://www.htsoft.com/resources/sd.c
> 
> Clyde

Thanks for posting the code.  I have been wanting to migrate from a CF
drive to SD/MMC.  Your driver will save me a lot of effort.

Richard

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.