EmbeddedRelated.com
Forums
Memfault Beyond the Launch

LPC2148 Philips App. Note MMC-SD Card interfacing AN1406_2

Started by goel_aditya2003 October 21, 2009
Hello people
I was trying to get this code running blindly in the beginning only to realize that there are loads of errors in this code. Has anyone actually implemented this code and got it running on hardware??
Thanks
Aditya

An Engineer's Guide to the LPC2100 Series

--- In l..., "goel_aditya2003" wrote:
>
> Hello people
> I was trying to get this code running blindly in the beginning only to realize that there are loads of errors in this code. Has anyone actually implemented this code and got it running on hardware??
> Thanks
> Aditya
>

There a -3 version: http://www.nxp.com/acrobat/applicationnotes/AN10406_3.pdf

There's good info here: http://openhardware.net/Embedded_ARM/RDCF2/

There's really good code here: www.jcwren.com/arm

Richard

The newer version still uses the same code. One of the biggest error which I
think is that MMC card initialization is in MHz!!!It is usually between 100
KHz and 400 KHz.
I am interested in implementing Chan's file system. So i thought i should
get this code to work first.

Thanks
Aditya

On Wed, Oct 21, 2009 at 11:42 PM, rtstofer wrote:

> --- In l... ,
> "goel_aditya2003" wrote:
> >
> > Hello people
> > I was trying to get this code running blindly in the beginning only to
> realize that there are loads of errors in this code. Has anyone actually
> implemented this code and got it running on hardware??
> > Thanks
> > Aditya
> > There a -3 version:
> http://www.nxp.com/acrobat/applicationnotes/AN10406_3.pdf
>
> There's good info here: http://openhardware.net/Embedded_ARM/RDCF2/
>
> There's really good code here: www.jcwren.com/arm
>
> Richard
>
>
>


Meanwhile I will have a look at jcwren's code.
Thanks
Aditya

On Thu, Oct 22, 2009 at 12:01 AM, ADITYA GOEL wrote:

> The newer version still uses the same code. One of the biggest error which
> I think is that MMC card initialization is in MHz!!!It is usually between
> 100 KHz and 400 KHz.
> I am interested in implementing Chan's file system. So i thought i should
> get this code to work first.
>
> Thanks
> Aditya
> On Wed, Oct 21, 2009 at 11:42 PM, rtstofer wrote:
>
>> --- In l... ,
>> "goel_aditya2003" wrote:
>> >
>> > Hello people
>> > I was trying to get this code running blindly in the beginning only to
>> realize that there are loads of errors in this code. Has anyone actually
>> implemented this code and got it running on hardware??
>> > Thanks
>> > Aditya
>> >
>>
>> There a -3 version:
>> http://www.nxp.com/acrobat/applicationnotes/AN10406_3.pdf
>>
>> There's good info here: http://openhardware.net/Embedded_ARM/RDCF2/
>>
>> There's really good code here: www.jcwren.com/arm
>>
>> Richard
>>
>>
>>


Hi Aditya,

I got it working on an LPC2103, no problem at all. The code in the application note was written for an LPC2148, and all I had to do was changing the I/O pin allocation accordingly. Frequency is not a matter in this case, since SPI can work up to 20 MHz. There is an application note on "How to Use MMC/SDC" (goggle it) that shows how to set the SD card appropriately, including the need for pull-ups on some data and unused lines.

I can't post the code, because I am using it on a comercial design. Sorry :(

But rest assured that IT DOES WORK, as published, you just have to do your homework (I hope you're not one of those "easy-going" freshman running after a quick solution for their end-of-semester projects). And contrary to your belief, "there aren't loads of errors" in the code. Yes, a couple here and there, but nothing that a good programmer wouldn't catch by simulating it, say under Keil's uVision.

One example that I remember (I did this some eight months ago) was in the lines that define the low and high bytes of the block to be read or written. Instead of:
varl=((block_number&0x003F)<<9);
varh=((block_number&0xFFC0)>>7);
they should read:
varl=((block_number & 0x007F)<<9);
varh=((block_number & 0xFF80)>>7);

Good luck,

Julio de Melo

--- In l..., "goel_aditya2003" wrote:
>
> Hello people
> I was trying to get this code running blindly in the beginning only to realize that there are loads of errors in this code. Has anyone actually implemented this code and got it running on hardware??
> Thanks
> Aditya
>

I have been trying to get it working on the lpc for 2 days now. One of the
major errors which I think is during the initialization of the MMC. All the
sites on internet suggest that in the initialization part where I send
CMD0,CMD1 and CMD8 should be done at lower rate than the reading and writing
process. Reading and writing can be done at around 20 MHz whereas this
initialization has to be done from 100 to 400 KHz. Correct me if I am wrong.

Thanks
Aditya
PS: Not a mid term project. We have been working on a product development
project for about an year now and this comes as a part of it :D
On Thu, Oct 22, 2009 at 7:42 PM, jcdmelo wrote:

> Hi Aditya,
>
> I got it working on an LPC2103, no problem at all. The code in the
> application note was written for an LPC2148, and all I had to do was
> changing the I/O pin allocation accordingly. Frequency is not a matter in
> this case, since SPI can work up to 20 MHz. There is an application note on
> "How to Use MMC/SDC" (goggle it) that shows how to set the SD card
> appropriately, including the need for pull-ups on some data and unused
> lines.
>
> I can't post the code, because I am using it on a comercial design. Sorry
> :(
>
> But rest assured that IT DOES WORK, as published, you just have to do your
> homework (I hope you're not one of those "easy-going" freshman running after
> a quick solution for their end-of-semester projects). And contrary to your
> belief, "there aren't loads of errors" in the code. Yes, a couple here and
> there, but nothing that a good programmer wouldn't catch by simulating it,
> say under Keil's uVision.
>
> One example that I remember (I did this some eight months ago) was in the
> lines that define the low and high bytes of the block to be read or written.
> Instead of:
> varl=((block_number&0x003F)<<9);
> varh=((block_number&0xFFC0)>>7);
> they should read:
> varl=((block_number & 0x007F)<<9);
> varh=((block_number & 0xFF80)>>7);
>
> Good luck,
>
> Julio de Melo
> --- In l... ,
> "goel_aditya2003" wrote:
> >
> > Hello people
> > I was trying to get this code running blindly in the beginning only to
> realize that there are loads of errors in this code. Has anyone actually
> implemented this code and got it running on hardware??
> > Thanks
> > Aditya
> >
>


All my communications are done at the same rate - 12Mhz. Never had a
problem and I use a LPC2148. I use all types and sizes of SD cards.
Works fine. I can write files from my embedded system and read them in
Windows, and vice-versa.

Send me your init code and I'll see if I see anything.

Sutton

ADITYA GOEL wrote:
>
>
> I have been trying to get it working on the lpc for 2 days now. One of the
> major errors which I think is during the initialization of the MMC. All the
> sites on internet suggest that in the initialization part where I send
> CMD0,CMD1 and CMD8 should be done at lower rate than the reading and writing
> process. Reading and writing can be done at around 20 MHz whereas this
> initialization has to be done from 100 to 400 KHz. Correct me if I am wrong.
>
> Thanks
> Aditya
> PS: Not a mid term project. We have been working on a product development
> project for about an year now and this comes as a part of it :D
>
> On Thu, Oct 22, 2009 at 7:42 PM, jcdmelo > > wrote:
>
> >
> >
> >
> >
> > Hi Aditya,
> >
> > I got it working on an LPC2103, no problem at all. The code in the
> > application note was written for an LPC2148, and all I had to do was
> > changing the I/O pin allocation accordingly. Frequency is not a matter in
> > this case, since SPI can work up to 20 MHz. There is an application
> note on
> > "How to Use MMC/SDC" (goggle it) that shows how to set the SD card
> > appropriately, including the need for pull-ups on some data and unused
> > lines.
> >
> > I can't post the code, because I am using it on a comercial design. Sorry
> > :(
> >
> > But rest assured that IT DOES WORK, as published, you just have to do
> your
> > homework (I hope you're not one of those "easy-going" freshman
> running after
> > a quick solution for their end-of-semester projects). And contrary to
> your
> > belief, "there aren't loads of errors" in the code. Yes, a couple
> here and
> > there, but nothing that a good programmer wouldn't catch by
> simulating it,
> > say under Keil's uVision.
> >
> > One example that I remember (I did this some eight months ago) was in the
> > lines that define the low and high bytes of the block to be read or
> written.
> > Instead of:
> > varl=((block_number&0x003F)<<9);
> > varh=((block_number&0xFFC0)>>7);
> > they should read:
> > varl=((block_number & 0x007F)<<9);
> > varh=((block_number & 0xFF80)>>7);
> >
> > Good luck,
> >
> > Julio de Melo
> >
> >
> > --- In l...
> ,
> > "goel_aditya2003" wrote:
> > >
> > > Hello people
> > > I was trying to get this code running blindly in the beginning only to
> > realize that there are loads of errors in this code. Has anyone actually
> > implemented this code and got it running on hardware??
> > > Thanks
> > > Aditya
> > >
> >
> >
> >

--
Sutton Mehaffey
Lookout Portable Security
4040 Royal Dr.
Kennesaw, GA 30144
770-514-7999, 800-207-6269
Fax: 770-514-1285
http://www.lookoutportablesecurity.com
s...@lookoutportablesecurity.com

/*-----------------------------------
* Name: SPI_MMC.C
* Purpose: SPI and SD/MMC command interface Module
* Version: V1.03
* Copyright (c) 2006 NXP Semiconductor. All rights reserved.
*---------------------------------*/
#include /* LPC214x definitions */
#include "type.h"
#include "spi_mmc.h"
#include "mmcmain.h"
#include

BYTE MMCWRData[MMC_DATA_SIZE];
BYTE MMCRDData[MMC_DATA_SIZE];
BYTE MMCCmd[MMC_CMD_SIZE];
BYTE MMCStatus = 0;
/*
* SPI and MMC commands related modules.
*
*/
void SPI_Init( void )
{ //DWORD portConfig;//ch
BYTE i, Dummy;
/* Configure PIN connect block */
/* bit 32, 54, 76 are 0x10, bit 98 are 0x00
port 0 bits 17, 18, 19, 20 are SSP port SCK1, MISO1, MOSI1,
and SSEL1 set SSEL to GPIO pin that you will have the totoal
freedom to set/reset the SPI chip-select pin */
SSPCR1 = 0x00; /* SSP master (off) in normal mode */
//portConfig = PINSEL1;//ch
//PINSEL1 = portConfig | 0x00A8;//ch
PINSEL1 = PINSEL1 | 0x00A8; // right 0a8 as we r using it as a gpio
IODIR0 = SPI_SEL; /* SSEL is output */
IOSET0 = SPI_SEL; /* set SSEL to high */

/* Set PCLK 1/2 of CCLK */
//VPBDIV = 0x02;
VPBDIV = 0x04;//right
/* Set data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 0,
and SCR is 15 */
//SSPCR0 = 0x0707;
//SSPCR0 = 0x0F07;
//SSPCR0 = 0x1107;
SSPCR0 = 0x0007; //right 400 khz initially
/* SSPCPSR clock prescale register, master mode, minimum divisor
is 0x02*/
SSPCPSR = 0x36; //right
/* Device select as master, SSP Enabled, normal operational mode */
SSPCR1 = 0x02; //right
for ( i = 0; i < 8; i++ )
{
Dummy = SSPDR; /* clear the RxFIFO */
}

return;
}
/*
* SPI Send a block of data based on the length
*/
void SPI_Send( BYTE *buf, DWORD Length )
{
BYTE Dummy;
if ( Length == 0 )
return;
while ( Length != 0 )
{
/* as long as TNF bit is set, TxFIFO is not full, I can write */
while ( !(SSPSR & 0x02) ); //rt
SSPDR = *buf;
/* Wait until the Busy bit is cleared */
while (SSPSR & 0x10) ;//
while (!(SSPSR & 0x04)) ; //
Dummy = SSPDR; /* Flush the RxFIFO */
Length--;
buf++;
}
return;
}
/*
* SPI receives a block of data based on the length
*/
void SPI_Receive( BYTE *buf, DWORD Length )
{
DWORD i;
for ( i = 0; i < Length; i++ )
{
*buf = SPI_ReceiveByte();
buf++;
}
return;
}
/*
* SPI Receive Byte, receive one byte only, return Data byte
* used a lot to check the status.
*/
BYTE SPI_ReceiveByte( void )
{
BYTE data;
/* wrtie dummy byte out to generate clock, then read data from
MISO */
while ( SSPSR & 0x10 );
while ( !(SSPSR & 0x02) );
SSPDR = 0xFF;
/* Wait until the Busy bit is cleared */
while ( SSPSR & 0x10 ); //
while (!(SSPSR & 0x04)) ;//
data = SSPDR;
return ( data );
}
/************************** MMC Init *********************************/
/*
* Initialises the MMC into SPI mode and sets block size(512), returns
* 0 on success
*
*/

int mmc_init()
{
DWORD i,k,result;

/* Generate a data pattern for write block */
for(i=0;i {
MMCWRData[i] = i;
}
MMCStatus = 0;
for(k=0;k<2;k++)
{
IOSET0 = SPI_SEL; /* set SPI SSEL *///

/* initialise the MMC card into SPI mode by sending 80 clks on */
/* Use MMCRDData as a temporary buffer for SPI_Send() */
for(i=0; i<20; i++)
{
MMCRDData[i] = 0xFF; //rt
}
SPI_Send( MMCRDData, 20 );
IOCLR0 = SPI_SEL; /* clear SPI SSEL *///

/* send CMD0(RESET or GO_IDLE_STATE) command, all the arguments
are 0x00 for the reset command, precalculated checksum */
MMCCmd[0] = 0x40; //rt
MMCCmd[1] = 0x00;
MMCCmd[2] = 0x00;
MMCCmd[3] = 0x00;
MMCCmd[4] = 0x00;
MMCCmd[5] = 0x95; //rt
SPI_Send( MMCCmd, MMC_CMD_SIZE );
// printf("") ;
/* if = 1 then there was a timeout waiting for 0x01 from the MMC */
result= mmc_response(0x01);
if( result == 0 )
{
break;
}
}

if( result == 1 )
{
MMCStatus = IDLE_STATE_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
/* Send some dummy clocks after GO_IDLE_STATE */
IOSET0 = SPI_SEL; /* set SPI SSEL */ //doubtful of these 3 commands //y
making high
SPI_ReceiveByte();
IOCLR0 = SPI_SEL; /* clear SPI SSEL */
/* must keep sending command until zero response is back. */
i = MAX_TIMEOUT;
do
{
/* send mmc CMD1(SEND_OP_COND) to bring out of idle state */
/* all the arguments are 0x00 for command one */
MMCCmd[0] = 0x41; //rt
MMCCmd[1] = 0x00;
MMCCmd[2] = 0x00;
MMCCmd[3] = 0x00;
MMCCmd[4] = 0x00;
/* checksum is no longer required but we always send 0xFF */
MMCCmd[5] = 0xFF;
SPI_Send( MMCCmd, MMC_CMD_SIZE );
i--;
} while ( (mmc_response(0x00) != 0) && (i>0) ); //rt
/* timeout waiting for 0x00 from the MMC */
if ( i == 0 )
{
MMCStatus = OP_COND_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
/* Send some dummy clocks after SEND_OP_COND */
IOSET0 = SPI_SEL; /* set SPI SSEL *///again
SPI_ReceiveByte();
IOCLR0 = SPI_SEL; /* clear SPI SSEL */
/* send MMC CMD16(SET_BLOCKLEN) to set the block length */
MMCCmd[0] = 0x50;
MMCCmd[1] = 0x00; /* 4 bytes from here is the block length */
/* LSB is first */
/* 00 00 00 10 set to 16 bytes */
/* 00 00 02 00 set to 512 bytes */
MMCCmd[2] = 0x00;
/* high block length bits - 512 bytes */
MMCCmd[3] = 0x02;
/* low block length bits */
MMCCmd[4] = 0x00;
/* checksum is no longer required but we always send 0xFF */
MMCCmd[5] = 0xFF;
SPI_Send( MMCCmd, MMC_CMD_SIZE ); //rt
if( (mmc_response(0x00))==1 )
{
MMCStatus = SET_BLOCKLEN_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
IOSET0 = SPI_SEL; /* set SPI SSEL */ ///again dunno y
SPI_ReceiveByte();
return 0;
}
/************************** MMC Write Block ***************************/
/* write a block of data based on the length that has been set
* in the SET_BLOCKLEN command.
* Send the WRITE_SINGLE_BLOCK command out first, check the
* R1 response, then send the data start token(bit 0 to 0) followed by
* the block of data. The test program sets the block length to 512
* bytes. When the data write finishs, the response should come back
* as 0xX5 bit 3 to 0 as 0101B, then another non-zero value indicating
* that MMC card is in idle state again.
*
*/
int mmc_write_block(WORD block_number)
{
WORD varl, varh;
BYTE Status;
IOCLR0 = SPI_SEL; /* clear SPI SSEL */
/* block size has been set in mmc_init() */
//varl=((block_number&0x003F)<<9); // not sure diff. on internet
//varh=((block_number&0xFFC0)>>7); // not sure diff. on internet
varl=((block_number&0x007F)<<9); //new one
varh=((block_number&0xFF80)>>7); //new one
/* send mmc CMD24(WRITE_SINGLE_BLOCK) to write the data to MMC card */
MMCCmd[0] = 0x58;
/* high block address bits, varh HIGH and LOW */
MMCCmd[1] = varh >> 0x08;
MMCCmd[2] = varh & 0xFF;
/* low block address bits, varl HIGH and LOW */
MMCCmd[3] = varl >> 0x08;
MMCCmd[4] = varl & 0xFF;
/* checksum is no longer required but we always send 0xFF */
MMCCmd[5] = 0xFF;
SPI_Send(MMCCmd, MMC_CMD_SIZE );
/* if mmc_response returns 1 then we failed to get a 0x00 response */
if((mmc_response(0x00))==1)
{
MMCStatus = WRITE_BLOCK_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
/* Set bit 0 to 0 which indicates the beginning of the data block */
MMCCmd[0] = 0xFE;
SPI_Send( MMCCmd, 1 );//rt
/* send data, pattern as 0x00,0x01,0x02,0x03,0x04,0x05 ...*/
SPI_Send( MMCWRData, MMC_DATA_SIZE );
/* Send dummy checksum */
/* when the last check sum is sent, the response should come back
immediately. So, check the SPI FIFO MISO and make sure the status
return 0xX5, the bit 3 through 0 should be 0x05 */
MMCCmd[0] = 0xFF;
MMCCmd[1] = 0xFF;
SPI_Send( MMCCmd, 2 );
Status = SPI_ReceiveByte();
if ( (Status & 0x0F) != 0x05 )
{
MMCStatus = WRITE_BLOCK_FAIL;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
/* if the status is already zero, the write hasn't finished
yet and card is busy */
if(mmc_wait_for_write_finish()==1)
{
MMCStatus = WRITE_BLOCK_FAIL;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
IOSET0 = SPI_SEL; /* set SPI SSEL */ //yyyyy????
SPI_ReceiveByte();
return 0;
}
/************************** MMC Read Block ****************************/
/*
* Reads a 512 Byte block from the MMC
* Send READ_SINGLE_BLOCK command first, wait for response come back
* 0x00 followed by 0xFE. The call SPI_Receive() to read the data
* block back followed by the checksum.
*
*/
int mmc_read_block(WORD block_number)
{
WORD Checksum;
WORD varh,varl;
IOCLR0 = SPI_SEL; /* clear SPI SSEL */
//varl=((block_number&0x003F)<<9);
//varh=((block_number&0xFFC0)>>7);
varl=((block_number&0x007F)<<9);
varh=((block_number&0xFF80)>>7);
/* send MMC CMD17(READ_SINGLE_BLOCK) to read the data from MMC card */
MMCCmd[0] = 0x51;
/* high block address bits, varh HIGH and LOW */
MMCCmd[1] = varh >> 0x08;
MMCCmd[2] = varh & 0xFF;
/* low block address bits, varl HIGH and LOW */
MMCCmd[3] = varl >> 0x08;
MMCCmd[4] = varl & 0xFF;
/* checksum is no longer required but we always send 0xFF */
MMCCmd[5] = 0xFF;
SPI_Send(MMCCmd, MMC_CMD_SIZE ); //rt
/* if mmc_response returns 1 then we failed to get a 0x00 response */
if((mmc_response(0x00))==1)
{
MMCStatus = READ_BLOCK_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
/* wait for data token */

if((mmc_response(0xFE))==1)
{
MMCStatus = READ_BLOCK_DATA_TOKEN_MISSING;
IOSET0 = SPI_SEL;
return MMCStatus;
}
/* Get the block of data based on the length */
SPI_Receive( MMCRDData, MMC_DATA_SIZE );
/* CRC bytes that are not needed */
Checksum = SPI_ReceiveByte();
Checksum = Checksum << 0x08 | SPI_ReceiveByte();//rt
IOSET0 = SPI_SEL; /* set SPI SSEL */
SPI_ReceiveByte(); //yyyy??
return 0;
}
/***************** MMC get response *******************/
/*
* Repeatedly reads the MMC until we get the
* response we want or timeout
*/
int mmc_response( BYTE response)
{
DWORD count = 0xFF;
BYTE result;
while( count > 0 )
{
result = SPI_ReceiveByte();
//printf(result);
if ( result == response )
{
break;
}
count--;
}
if ( count == 0 )
return 1; /* Failure, loop was exited due to timeout */
else
return 0; /* Normal, loop was exited before timeout */
}
/***************** MMC wait for write finish *******************/
/*
* Repeatedly reads the MMC until we get a non-zero value (after
* a zero value) indicating the write has finished and card is no
* longer busy.
*
*/
int mmc_wait_for_write_finish( void )
{
DWORD count = 0xFFFF; /* The delay is set to maximum considering
the longest data block length to handle */
BYTE result = 0;
while( (result == 0) && count )
{
result = SPI_ReceiveByte();

count--;
}
if ( count == 0 )
return 1; /* Failure, loop was exited due to timeout */
else
return 0; /* Normal, loop was exited before timeout */
}

On Thu, Oct 22, 2009 at 8:25 PM, Sutton Mehaffey <
s...@lookoutportablesecurity.com> wrote:

> All my communications are done at the same rate - 12Mhz. Never had a
> problem and I use a LPC2148. I use all types and sizes of SD cards.
> Works fine. I can write files from my embedded system and read them in
> Windows, and vice-versa.
>
> Send me your init code and I'll see if I see anything.
>
> Sutton
> ADITYA GOEL wrote:
> >
> >
> > I have been trying to get it working on the lpc for 2 days now. One of
> the
> > major errors which I think is during the initialization of the MMC. All
> the
> > sites on internet suggest that in the initialization part where I send
> > CMD0,CMD1 and CMD8 should be done at lower rate than the reading and
> writing
> > process. Reading and writing can be done at around 20 MHz whereas this
> > initialization has to be done from 100 to 400 KHz. Correct me if I am
> wrong.
> >
> > Thanks
> > Aditya
> > PS: Not a mid term project. We have been working on a product development
> > project for about an year now and this comes as a part of it :D
> >
> > On Thu, Oct 22, 2009 at 7:42 PM, jcdmelo
> > >> wrote:
> >
> > >
> > >
> > >
> > >
> > > Hi Aditya,
> > >
> > > I got it working on an LPC2103, no problem at all. The code in the
> > > application note was written for an LPC2148, and all I had to do was
> > > changing the I/O pin allocation accordingly. Frequency is not a matter
> in
> > > this case, since SPI can work up to 20 MHz. There is an application
> > note on
> > > "How to Use MMC/SDC" (goggle it) that shows how to set the SD card
> > > appropriately, including the need for pull-ups on some data and unused
> > > lines.
> > >
> > > I can't post the code, because I am using it on a comercial design.
> Sorry
> > > :(
> > >
> > > But rest assured that IT DOES WORK, as published, you just have to do
> > your
> > > homework (I hope you're not one of those "easy-going" freshman
> > running after
> > > a quick solution for their end-of-semester projects). And contrary to
> > your
> > > belief, "there aren't loads of errors" in the code. Yes, a couple
> > here and
> > > there, but nothing that a good programmer wouldn't catch by
> > simulating it,
> > > say under Keil's uVision.
> > >
> > > One example that I remember (I did this some eight months ago) was in
> the
> > > lines that define the low and high bytes of the block to be read or
> > written.
> > > Instead of:
> > > varl=((block_number&0x003F)<<9);
> > > varh=((block_number&0xFFC0)>>7);
> > > they should read:
> > > varl=((block_number & 0x007F)<<9);
> > > varh=((block_number & 0xFF80)>>7);
> > >
> > > Good luck,
> > >
> > > Julio de Melo
> > >
> > >
> > > --- In l... > lpc2000%40yahoogroups.com >
> > ,
> > > "goel_aditya2003" wrote:
> > > >
> > > > Hello people
> > > > I was trying to get this code running blindly in the beginning only
> to
> > > realize that there are loads of errors in this code. Has anyone
> actually
> > > implemented this code and got it running on hardware??
> > > > Thanks
> > > > Aditya
> > > >
> > >
> > >
> > >
> >
> >
> >
> > --
> Sutton Mehaffey
> Lookout Portable Security
> 4040 Royal Dr.
> Kennesaw, GA 30144
> 770-514-7999, 800-207-6269
> Fax: 770-514-1285
> http://www.lookoutportablesecurity.com
> s...@lookoutportablesecurity.com
>


BYTE MMCWRData[MMC_DATA_SIZE];
BYTE MMCRDData[MMC_DATA_SIZE];
BYTE MMCCmd[MMC_CMD_SIZE];
BYTE MMCStatus = 0;
/*
* SPI and MMC commands related modules.
*
*/
void SPI_Init( void )
{ //DWORD portConfig;//ch
BYTE i, Dummy;
/* Configure PIN connect block */
/* bit 32, 54, 76 are 0x10, bit 98 are 0x00
port 0 bits 17, 18, 19, 20 are SSP port SCK1, MISO1, MOSI1,
and SSEL1 set SSEL to GPIO pin that you will have the totoal
freedom to set/reset the SPI chip-select pin */
SSPCR1 = 0x00; /* SSP master (off) in normal mode */
//portConfig = PINSEL1;//ch
//PINSEL1 = portConfig | 0x00A8;//ch
PINSEL1 = PINSEL1 | 0x00A8; // right 0a8 as we r using it as a gpio
IODIR0 = SPI_SEL; /* SSEL is output */
IOSET0 = SPI_SEL; /* set SSEL to high */

/* Set PCLK 1/2 of CCLK */
//VPBDIV = 0x02;
VPBDIV = 0x04;//right
/* Set data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 0,
and SCR is 15 */
//SSPCR0 = 0x0707;
//SSPCR0 = 0x0F07;
//SSPCR0 = 0x1107;
SSPCR0 = 0x0007; //right 400 khz initially
/* SSPCPSR clock prescale register, master mode, minimum divisor
is 0x02*/
SSPCPSR = 0x36; //right
/* Device select as master, SSP Enabled, normal operational mode */
SSPCR1 = 0x02; //right
for ( i = 0; i < 8; i++ )
{
Dummy = SSPDR; /* clear the RxFIFO */
}

return;
}
/*
* SPI Send a block of data based on the length
*/
void SPI_Send( BYTE *buf, DWORD Length )
{
BYTE Dummy;
if ( Length == 0 )
return;
while ( Length != 0 )
{
/* as long as TNF bit is set, TxFIFO is not full, I can write */
while ( !(SSPSR & 0x02) ); //rt
SSPDR = *buf;
/* Wait until the Busy bit is cleared */
while (SSPSR & 0x10) ;//
while (!(SSPSR & 0x04)) ; //
Dummy = SSPDR; /* Flush the RxFIFO */
Length--;
buf++;
}
return;
}
/*
* SPI receives a block of data based on the length
*/
void SPI_Receive( BYTE *buf, DWORD Length )
{
DWORD i;
for ( i = 0; i < Length; i++ )
{
*buf = SPI_ReceiveByte();
buf++;
}
return;
}
/*
* SPI Receive Byte, receive one byte only, return Data byte
* used a lot to check the status.
*/
BYTE SPI_ReceiveByte( void )
{
BYTE data;
/* wrtie dummy byte out to generate clock, then read data from
MISO */
while ( SSPSR & 0x10 );
while ( !(SSPSR & 0x02) );
SSPDR = 0xFF;
/* Wait until the Busy bit is cleared */
while ( SSPSR & 0x10 ); //
while (!(SSPSR & 0x04)) ;//
data = SSPDR;
return ( data );
}
/************************** MMC Init *********************************/
/*
* Initialises the MMC into SPI mode and sets block size(512), returns
* 0 on success
*
*/

int mmc_init()
{
DWORD i,k,result;

/* Generate a data pattern for write block */
for(i=0;i {
MMCWRData[i] = i;
}
MMCStatus = 0;
for(k=0;k<2;k++)
{
IOSET0 = SPI_SEL; /* set SPI SSEL *///

/* initialise the MMC card into SPI mode by sending 80 clks on */
/* Use MMCRDData as a temporary buffer for SPI_Send() */
for(i=0; i<20; i++)
{
MMCRDData[i] = 0xFF; //rt
}
SPI_Send( MMCRDData, 20 );
IOCLR0 = SPI_SEL; /* clear SPI SSEL *///

/* send CMD0(RESET or GO_IDLE_STATE) command, all the arguments
are 0x00 for the reset command, precalculated checksum */
MMCCmd[0] = 0x40; //rt
MMCCmd[1] = 0x00;
MMCCmd[2] = 0x00;
MMCCmd[3] = 0x00;
MMCCmd[4] = 0x00;
MMCCmd[5] = 0x95; //rt
SPI_Send( MMCCmd, MMC_CMD_SIZE );
// printf("") ;
/* if = 1 then there was a timeout waiting for 0x01 from the MMC */
result= mmc_response(0x01);
if( result == 0 )
{
break;
}
}

if( result == 1 )
{
MMCStatus = IDLE_STATE_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
/* Send some dummy clocks after GO_IDLE_STATE */
IOSET0 = SPI_SEL; /* set SPI SSEL */ //doubtful of these 3 commands //y
making high
SPI_ReceiveByte();
IOCLR0 = SPI_SEL; /* clear SPI SSEL */
/* must keep sending command until zero response is back. */
i = MAX_TIMEOUT;
do
{
/* send mmc CMD1(SEND_OP_COND) to bring out of idle state */
/* all the arguments are 0x00 for command one */
MMCCmd[0] = 0x41; //rt
MMCCmd[1] = 0x00;
MMCCmd[2] = 0x00;
MMCCmd[3] = 0x00;
MMCCmd[4] = 0x00;
/* checksum is no longer required but we always send 0xFF */
MMCCmd[5] = 0xFF;
SPI_Send( MMCCmd, MMC_CMD_SIZE );
i--;
} while ( (mmc_response(0x00) != 0) && (i>0) ); //rt
/* timeout waiting for 0x00 from the MMC */
if ( i == 0 )
{
MMCStatus = OP_COND_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
/* Send some dummy clocks after SEND_OP_COND */
IOSET0 = SPI_SEL; /* set SPI SSEL *///again
SPI_ReceiveByte();
IOCLR0 = SPI_SEL; /* clear SPI SSEL */
/* send MMC CMD16(SET_BLOCKLEN) to set the block length */
MMCCmd[0] = 0x50;
MMCCmd[1] = 0x00; /* 4 bytes from here is the block length */
/* LSB is first */
/* 00 00 00 10 set to 16 bytes */
/* 00 00 02 00 set to 512 bytes */
MMCCmd[2] = 0x00;
/* high block length bits - 512 bytes */
MMCCmd[3] = 0x02;
/* low block length bits */
MMCCmd[4] = 0x00;
/* checksum is no longer required but we always send 0xFF */
MMCCmd[5] = 0xFF;
SPI_Send( MMCCmd, MMC_CMD_SIZE ); //rt
if( (mmc_response(0x00))==1 )
{
MMCStatus = SET_BLOCKLEN_TIMEOUT;
IOSET0 = SPI_SEL; /* set SPI SSEL */
return MMCStatus;
}
IOSET0 = SPI_SEL; /* set SPI SSEL */ ///again dunno y
SPI_ReceiveByte();
return 0;
}

/***************** MMC get response *******************/
/*
* Repeatedly reads the MMC until we get the
* response we want or timeout
*/
int mmc_response( BYTE response)
{
DWORD count = 0xFF;
BYTE result;
while( count > 0 )
{
result = SPI_ReceiveByte();
//printf(result);
if ( result == response )
{
break;
}
count--;
}
if ( count == 0 )
return 1; /* Failure, loop was exited due to timeout */
else
return 0; /* Normal, loop was exited before timeout */
}

>


Maybe you have answered this before, but where is it failing in your
init sequence? What command status is not as you expect?

Sutton

ADITYA GOEL wrote:
>
>
> /*----------------------
> * Name: SPI_MMC.C
> * Purpose: SPI and SD/MMC command interface Module
> * Version: V1.03
> * Copyright (c) 2006 NXP Semiconductor. All rights reserved.
> *----------------------*/
> #include /* LPC214x definitions */
> #include "type.h"
> #include "spi_mmc.h"
> #include "mmcmain.h"
> #include BYTE MMCWRData[MMC_DATA_SIZE];
> BYTE MMCRDData[MMC_DATA_SIZE];
> BYTE MMCCmd[MMC_CMD_SIZE];
> BYTE MMCStatus = 0;
> /*
> * SPI and MMC commands related modules.
> *
> */
> void SPI_Init( void )
> { //DWORD portConfig;//ch
> BYTE i, Dummy;
> /* Configure PIN connect block */
> /* bit 32, 54, 76 are 0x10, bit 98 are 0x00
> port 0 bits 17, 18, 19, 20 are SSP port SCK1, MISO1, MOSI1,
> and SSEL1 set SSEL to GPIO pin that you will have the totoal
> freedom to set/reset the SPI chip-select pin */
> SSPCR1 = 0x00; /* SSP master (off) in normal mode */
> //portConfig = PINSEL1;//ch
> //PINSEL1 = portConfig | 0x00A8;//ch
> PINSEL1 = PINSEL1 | 0x00A8; // right 0a8 as we r using it as a gpio
> IODIR0 = SPI_SEL; /* SSEL is output */
> IOSET0 = SPI_SEL; /* set SSEL to high */
>
> /* Set PCLK 1/2 of CCLK */
> //VPBDIV = 0x02;
> VPBDIV = 0x04;//right
> /* Set data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 0,
> and SCR is 15 */
> //SSPCR0 = 0x0707;
> //SSPCR0 = 0x0F07;
> //SSPCR0 = 0x1107;
> SSPCR0 = 0x0007; //right 400 khz initially
> /* SSPCPSR clock prescale register, master mode, minimum divisor
> is 0x02*/
> SSPCPSR = 0x36; //right
> /* Device select as master, SSP Enabled, normal operational mode */
> SSPCR1 = 0x02; //right
> for ( i = 0; i < 8; i++ )
> {
> Dummy = SSPDR; /* clear the RxFIFO */
> }
>
> return;
> }
> /*
> * SPI Send a block of data based on the length
> */
> void SPI_Send( BYTE *buf, DWORD Length )
> {
> BYTE Dummy;
> if ( Length == 0 )
> return;
> while ( Length != 0 )
> {
> /* as long as TNF bit is set, TxFIFO is not full, I can write */
> while ( !(SSPSR & 0x02) ); //rt
> SSPDR = *buf;
> /* Wait until the Busy bit is cleared */
> while (SSPSR & 0x10) ;//
> while (!(SSPSR & 0x04)) ; //
> Dummy = SSPDR; /* Flush the RxFIFO */
> Length--;
> buf++;
> }
> return;
> }
> /*
> * SPI receives a block of data based on the length
> */
> void SPI_Receive( BYTE *buf, DWORD Length )
> {
> DWORD i;
> for ( i = 0; i < Length; i++ )
> {
> *buf = SPI_ReceiveByte();
> buf++;
> }
> return;
> }
>
> /*
> * SPI Receive Byte, receive one byte only, return Data byte
> * used a lot to check the status.
> */
> BYTE SPI_ReceiveByte( void )
> {
> BYTE data;
> /* wrtie dummy byte out to generate clock, then read data from
> MISO */
> while ( SSPSR & 0x10 );
> while ( !(SSPSR & 0x02) );
> SSPDR = 0xFF;
> /* Wait until the Busy bit is cleared */
> while ( SSPSR & 0x10 ); //
> while (!(SSPSR & 0x04)) ;//
> data = SSPDR;
> return ( data );
> }
> /************************** MMC Init *********************************/
> /*
> * Initialises the MMC into SPI mode and sets block size(512), returns
> * 0 on success
> *
> */
>
> int mmc_init()
> {
> DWORD i,k,result;
>
> /* Generate a data pattern for write block */
> for(i=0;i > {
> MMCWRData[i] = i;
> }
> MMCStatus = 0;
> for(k=0;k<2;k++)
> {
> IOSET0 = SPI_SEL; /* set SPI SSEL *///
>
> /* initialise the MMC card into SPI mode by sending 80 clks on */
> /* Use MMCRDData as a temporary buffer for SPI_Send() */
> for(i=0; i<20; i++)
> {
> MMCRDData[i] = 0xFF; //rt
> }
> SPI_Send( MMCRDData, 20 );
> IOCLR0 = SPI_SEL; /* clear SPI SSEL *///
>
> /* send CMD0(RESET or GO_IDLE_STATE) command, all the arguments
> are 0x00 for the reset command, precalculated checksum */
> MMCCmd[0] = 0x40; //rt
> MMCCmd[1] = 0x00;
> MMCCmd[2] = 0x00;
> MMCCmd[3] = 0x00;
> MMCCmd[4] = 0x00;
> MMCCmd[5] = 0x95; //rt
> SPI_Send( MMCCmd, MMC_CMD_SIZE );
> // printf("") ;
> /* if = 1 then there was a timeout waiting for 0x01 from the MMC */
> result= mmc_response(0x01);
> if( result == 0 )
> {
> break;
> }
> }
>
> if( result == 1 )
> {
> MMCStatus = IDLE_STATE_TIMEOUT;
> IOSET0 = SPI_SEL; /* set SPI SSEL */
> return MMCStatus;
> }
> /* Send some dummy clocks after GO_IDLE_STATE */
> IOSET0 = SPI_SEL; /* set SPI SSEL */ //doubtful of these 3 commands //y
> making high
> SPI_ReceiveByte();
> IOCLR0 = SPI_SEL; /* clear SPI SSEL */
> /* must keep sending command until zero response is back. */
> i = MAX_TIMEOUT;
> do
> {
> /* send mmc CMD1(SEND_OP_COND) to bring out of idle state */
> /* all the arguments are 0x00 for command one */
> MMCCmd[0] = 0x41; //rt
> MMCCmd[1] = 0x00;
> MMCCmd[2] = 0x00;
> MMCCmd[3] = 0x00;
> MMCCmd[4] = 0x00;
> /* checksum is no longer required but we always send 0xFF */
> MMCCmd[5] = 0xFF;
> SPI_Send( MMCCmd, MMC_CMD_SIZE );
> i--;
> } while ( (mmc_response(0x00) != 0) && (i>0) ); //rt
> /* timeout waiting for 0x00 from the MMC */
> if ( i == 0 )
> {
> MMCStatus = OP_COND_TIMEOUT;
> IOSET0 = SPI_SEL; /* set SPI SSEL */
> return MMCStatus;
> }
> /* Send some dummy clocks after SEND_OP_COND */
> IOSET0 = SPI_SEL; /* set SPI SSEL *///again
> SPI_ReceiveByte();
> IOCLR0 = SPI_SEL; /* clear SPI SSEL */
> /* send MMC CMD16(SET_BLOCKLEN) to set the block length */
> MMCCmd[0] = 0x50;
> MMCCmd[1] = 0x00; /* 4 bytes from here is the block length */
> /* LSB is first */
> /* 00 00 00 10 set to 16 bytes */
> /* 00 00 02 00 set to 512 bytes */
> MMCCmd[2] = 0x00;
> /* high block length bits - 512 bytes */
> MMCCmd[3] = 0x02;
> /* low block length bits */
> MMCCmd[4] = 0x00;
> /* checksum is no longer required but we always send 0xFF */
> MMCCmd[5] = 0xFF;
> SPI_Send( MMCCmd, MMC_CMD_SIZE ); //rt
> if( (mmc_response(0x00))==1 )
> {
> MMCStatus = SET_BLOCKLEN_TIMEOUT;
> IOSET0 = SPI_SEL; /* set SPI SSEL */
> return MMCStatus;
> }
> IOSET0 = SPI_SEL; /* set SPI SSEL */ ///again dunno y
> SPI_ReceiveByte();
> return 0;
> }
> /************************** MMC Write Block ***************************/
> /* write a block of data based on the length that has been set
> * in the SET_BLOCKLEN command.
> * Send the WRITE_SINGLE_BLOCK command out first, check the
> * R1 response, then send the data start token(bit 0 to 0) followed by
> * the block of data. The test program sets the block length to 512
> * bytes. When the data write finishs, the response should come back
> * as 0xX5 bit 3 to 0 as 0101B, then another non-zero value indicating
> * that MMC card is in idle state again.
> *
> */
> int mmc_write_block(WORD block_number)
> {
> WORD varl, varh;
> BYTE Status;
> IOCLR0 = SPI_SEL; /* clear SPI SSEL */
> /* block size has been set in mmc_init() */
> //varl=((block_number&0x003F)<<9); // not sure diff. on internet
> //varh=((block_number&0xFFC0)>>7); // not sure diff. on internet
> varl=((block_number&0x007F)<<9); //new one
> varh=((block_number&0xFF80)>>7); //new one
> /* send mmc CMD24(WRITE_SINGLE_BLOCK) to write the data to MMC card */
> MMCCmd[0] = 0x58;
> /* high block address bits, varh HIGH and LOW */
> MMCCmd[1] = varh >> 0x08;
> MMCCmd[2] = varh & 0xFF;
> /* low block address bits, varl HIGH and LOW */
> MMCCmd[3] = varl >> 0x08;
> MMCCmd[4] = varl & 0xFF;
> /* checksum is no longer required but we always send 0xFF */
> MMCCmd[5] = 0xFF;
> SPI_Send(MMCCmd, MMC_CMD_SIZE );
> /* if mmc_response returns 1 then we failed to get a 0x00 response */
> if((mmc_response(0x00))==1)
> {
> MMCStatus = WRITE_BLOCK_TIMEOUT;
> IOSET0 = SPI_SEL; /* set SPI SSEL */
> return MMCStatus;
> }
> /* Set bit 0 to 0 which indicates the beginning of the data block */
> MMCCmd[0] = 0xFE;
> SPI_Send( MMCCmd, 1 );//rt
> /* send data, pattern as 0x00,0x01,0x02,0x03,0x04,0x05 ...*/
> SPI_Send( MMCWRData, MMC_DATA_SIZE );
> /* Send dummy checksum */
> /* when the last check sum is sent, the response should come back
> immediately. So, check the SPI FIFO MISO and make sure the status
> return 0xX5, the bit 3 through 0 should be 0x05 */
> MMCCmd[0] = 0xFF;
> MMCCmd[1] = 0xFF;
> SPI_Send( MMCCmd, 2 );
> Status = SPI_ReceiveByte();
> if ( (Status & 0x0F) != 0x05 )
> {
> MMCStatus = WRITE_BLOCK_FAIL;
> IOSET0 = SPI_SEL; /* set SPI SSEL */
> return MMCStatus;
> }
> /* if the status is already zero, the write hasn't finished
> yet and card is busy */
> if(mmc_wait_for_write_finish()==1)
> {
> MMCStatus = WRITE_BLOCK_FAIL;
> IOSET0 = SPI_SEL; /* set SPI SSEL */
> return MMCStatus;
> }
> IOSET0 = SPI_SEL; /* set SPI SSEL */ //yyyyy????
> SPI_ReceiveByte();
> return 0;
> }
> /************************** MMC Read Block ****************************/
> /*
> * Reads a 512 Byte block from the MMC
> * Send READ_SINGLE_BLOCK command first, wait for response come back
> * 0x00 followed by 0xFE. The call SPI_Receive() to read the data
> * block back followed by the checksum.
> *
> */
> int mmc_read_block(WORD block_number)
> {
> WORD Checksum;
> WORD varh,varl;
> IOCLR0 = SPI_SEL; /* clear SPI SSEL */
> //varl=((block_number&0x003F)<<9);
> //varh=((block_number&0xFFC0)>>7);
> varl=((block_number&0x007F)<<9);
> varh=((block_number&0xFF80)>>7);
> /* send MMC CMD17(READ_SINGLE_BLOCK) to read the data from MMC card */
> MMCCmd[0] = 0x51;
> /* high block address bits, varh HIGH and LOW */
> MMCCmd[1] = varh >> 0x08;
> MMCCmd[2] = varh & 0xFF;
> /* low block address bits, varl HIGH and LOW */
> MMCCmd[3] = varl >> 0x08;
> MMCCmd[4] = varl & 0xFF;
> /* checksum is no longer required but we always send 0xFF */
> MMCCmd[5] = 0xFF;
> SPI_Send(MMCCmd, MMC_CMD_SIZE ); //rt
> /* if mmc_response returns 1 then we failed to get a 0x00 response */
> if((mmc_response(0x00))==1)
> {
> MMCStatus = READ_BLOCK_TIMEOUT;
> IOSET0 = SPI_SEL; /* set SPI SSEL */
> return MMCStatus;
> }
> /* wait for data token */
>
> if((mmc_response(0xFE))==1)
> {
> MMCStatus = READ_BLOCK_DATA_TOKEN_MISSING;
> IOSET0 = SPI_SEL;
> return MMCStatus;
> }
> /* Get the block of data based on the length */
> SPI_Receive( MMCRDData, MMC_DATA_SIZE );
> /* CRC bytes that are not needed */
> Checksum = SPI_ReceiveByte();
> Checksum = Checksum << 0x08 | SPI_ReceiveByte();//rt
> IOSET0 = SPI_SEL; /* set SPI SSEL */
> SPI_ReceiveByte(); //yyyy??
> return 0;
> }
> /***************** MMC get response *******************/
> /*
> * Repeatedly reads the MMC until we get the
> * response we want or timeout
> */
> int mmc_response( BYTE response)
> {
> DWORD count = 0xFF;
> BYTE result;
> while( count > 0 )
> {
> result = SPI_ReceiveByte();
> //printf(result);
> if ( result == response )
> {
> break;
> }
> count--;
> }
> if ( count == 0 )
> return 1; /* Failure, loop was exited due to timeout */
> else
> return 0; /* Normal, loop was exited before timeout */
> }
> /***************** MMC wait for write finish *******************/
> /*
> * Repeatedly reads the MMC until we get a non-zero value (after
> * a zero value) indicating the write has finished and card is no
> * longer busy.
> *
> */
> int mmc_wait_for_write_finish( void )
> {
> DWORD count = 0xFFFF; /* The delay is set to maximum considering
> the longest data block length to handle */
> BYTE result = 0;
> while( (result == 0) && count )
> {
> result = SPI_ReceiveByte();
>
> count--;
> }
> if ( count == 0 )
> return 1; /* Failure, loop was exited due to timeout */
> else
> return 0; /* Normal, loop was exited before timeout */
> }
>
> On Thu, Oct 22, 2009 at 8:25 PM, Sutton Mehaffey <
> s...@lookoutportablesecurity.com
> > wrote:
>
> >
> >
> > All my communications are done at the same rate - 12Mhz. Never had a
> > problem and I use a LPC2148. I use all types and sizes of SD cards.
> > Works fine. I can write files from my embedded system and read them in
> > Windows, and vice-versa.
> >
> > Send me your init code and I'll see if I see anything.
> >
> > Sutton
> >
> >
> > ADITYA GOEL wrote:
> > >
> > >
> > > I have been trying to get it working on the lpc for 2 days now. One of
> > the
> > > major errors which I think is during the initialization of the MMC. All
> > the
> > > sites on internet suggest that in the initialization part where I send
> > > CMD0,CMD1 and CMD8 should be done at lower rate than the reading and
> > writing
> > > process. Reading and writing can be done at around 20 MHz whereas this
> > > initialization has to be done from 100 to 400 KHz. Correct me if I am
> > wrong.
> > >
> > > Thanks
> > > Aditya
> > > PS: Not a mid term project. We have been working on a product
> development
> > > project for about an year now and this comes as a part of it :D
> > >
> > > On Thu, Oct 22, 2009 at 7:42 PM, jcdmelo >
> > > >> wrote:
> > >
> > > >
> > > >
> > > >
> > > >
> > > > Hi Aditya,
> > > >
> > > > I got it working on an LPC2103, no problem at all. The code in the
> > > > application note was written for an LPC2148, and all I had to do was
> > > > changing the I/O pin allocation accordingly. Frequency is not a
> matter
> > in
> > > > this case, since SPI can work up to 20 MHz. There is an application
> > > note on
> > > > "How to Use MMC/SDC" (goggle it) that shows how to set the SD card
> > > > appropriately, including the need for pull-ups on some data and
> unused
> > > > lines.
> > > >
> > > > I can't post the code, because I am using it on a comercial design.
> > Sorry
> > > > :(
> > > >
> > > > But rest assured that IT DOES WORK, as published, you just have to do
> > > your
> > > > homework (I hope you're not one of those "easy-going" freshman
> > > running after
> > > > a quick solution for their end-of-semester projects). And contrary to
> > > your
> > > > belief, "there aren't loads of errors" in the code. Yes, a couple
> > > here and
> > > > there, but nothing that a good programmer wouldn't catch by
> > > simulating it,
> > > > say under Keil's uVision.
> > > >
> > > > One example that I remember (I did this some eight months ago) was in
> > the
> > > > lines that define the low and high bytes of the block to be read or
> > > written.
> > > > Instead of:
> > > > varl=((block_number&0x003F)<<9);
> > > > varh=((block_number&0xFFC0)>>7);
> > > > they should read:
> > > > varl=((block_number & 0x007F)<<9);
> > > > varh=((block_number & 0xFF80)>>7);
> > > >
> > > > Good luck,
> > > >
> > > > Julio de Melo
> > > >
> > > >
> > > > --- In l...
> > > lpc2000%40yahoogroups.com >
> > > ,
> > > > "goel_aditya2003" wrote:
> > > > >
> > > > > Hello people
> > > > > I was trying to get this code running blindly in the beginning only
> > to
> > > > realize that there are loads of errors in this code. Has anyone
> > actually
> > > > implemented this code and got it running on hardware??
> > > > > Thanks
> > > > > Aditya
> > > > >
> > > >
> > > >
> > > >
> > >
> > >
> > >
> > >
> >
> > --
> > Sutton Mehaffey
> > Lookout Portable Security
> > 4040 Royal Dr.
> > Kennesaw, GA 30144
> > 770-514-7999, 800-207-6269
> > Fax: 770-514-1285
> > http://www.lookoutportablesecurity.com
>
> > s...@lookoutportablesecurity.com
>
>
> >
> >
> >

--
Sutton Mehaffey
Lookout Portable Security
4040 Royal Dr.
Kennesaw, GA 30144
770-514-7999, 800-207-6269
Fax: 770-514-1285
http://www.lookoutportablesecurity.com
s...@lookoutportablesecurity.com


Memfault Beyond the Launch