EmbeddedRelated.com
Forums
Memfault Beyond the Launch

EFSL and SDHC

Started by drproton2003 July 7, 2009
> -----Original Message-----
> From: l...
> [mailto:l...]On Behalf
> Of drproton2003
> Sent: Tuesday, July 07, 2009 11:35 PM
> To: l...
> Subject: [lpc2000] Re: EFSL and SDHC
> Well, I found the problem. It looks as though SDHC is only
> supported on the MCI, not the SPI. I simply did a search for
> SDHC in all the files. The only hit, other than the
> initialization routine was in lpc2000_mci.c. From there the
> only difference I could see is that when reading/writing a
> sector the address is multiplied by 512 for standard cards
> and not for SDHC.

Not finding SDHC in comments does not mean much. Most of the
SDHC support is handled in SD.c, and these routines are usually
used by all hardware drivers.

The reason that SDHC support didn't work in FIFO mode, is that
the main reading functions are not called in that interface,
as it requires something very different. Especially if any
form of performance is required.

Please take a look at some of my comments on the EFSL Sourceforge
forums as well, as there are a number of other shortcomings in
the library that I found some useful workarounds for. Specifically,
watch out for cache performance issues when writing a lot without
closing files.

>
> I did a quick bandaid test. I externed CardType from sd.c to
> lpc2000_sd.c. In the if_readBuf I added the following,
> likewise in if_writeBuf.
>
> if(CardType==1||CardType==2||CardType==4)
> if_Command(CMDREAD, 512 * address);
> if(CardType=)
> if_Command(CMDREAD, address);
>
> With this mod it works with the fifo for both SD and SDHC
> cards. By this I mean that I have successfully made files on
> both cards, but have no measures of reliability or stability.

That is good news. I thought it should not be too difficult. You may
want to change it to:

if ( !(CardType & 8) )
if_Command(CMDREAD, 512 * address);
else
if_Command(CMDREAD, address);

to simplify it slightly.

Prior versions were quite reliable after I applied a bunch of patches,
and fixed some other bugs that I found through my testing. These
MT versions are supposed to have all of those applied. Alas, many
new features have been added as well, and as you have found there
are obviously a number of bugs remaining.

>
> As to the problems with the non-fifo routines. Here is the
> function that clocks in the sector:
>
> static euint8 rcvr_datablock (
> hwInterface *iface,
> euint8 *buff, /* Data buffer to store received data */
> euint16 btr /* Byte count (must be even number) */
> )
> {
> euint8 token;
> euint16 retry;
>
> retry = LOOP_CNT_100;
> /* should retry 100ms */
> do {
> token = if_spiSend( iface, 0xff );
> retry--;
> } while ((token == 0xFF) && retry);
>
> if(token != 0xFE) {
> return 0; /* If not valid data token,
> retutn with error */
> }
>
> do { /* Receive the data
> block into buffer */
> if_spiSend( iface, *buff++ );
> if_spiSend( iface, *buff++ );
> } while (btr -= 2);
> if_spiSend( iface, 0xff); /* Discard CRC */
> if_spiSend( iface, 0xff); /* Discard CRC */
>
> return 1; /* Return with success */
> }
>
> and it calls:
>
> euint8 if_spiSend(hwInterface *iface, euint8 outgoing)
> {
> euint8 incoming;
>
> #if ( HW_ENDPOINT_LPC2000_SPINUM == 0 )
> S0SPDR = outgoing;
> while( !(S0SPSR & (1< > incoming = S0SPDR;
> #endif
>
> #if ( HW_ENDPOINT_LPC2000_SPINUM == 1 )
> while( !(SPI_STATUS_REG & (1< > SSPDR = outgoing;
> while( !(SPI_STATUS_REG & (1< > incoming = SSPDR;
> #endif
>
> return(incoming);
> }
>
> Seems to me like if_spiSend( iface, *buff++ ); should be
> something like *buff++=if_spiSend( iface, 0xFF);

What you propose looks correct when comparing to prior versions.
I don't know how MT would have missed this.

Mike

An Engineer's Guide to the LPC2100 Series

I've attempted to fix the non-fifo code. I made the fix to the readsector function and the card now initializes correctly. However I found a problem in the write function as well

static euint8 xmit_datablock (
hwInterface *iface,
const euint8 *buff, /* 512 byte data block to be transmitted */
euint8 token /* Data/Stop token */
)
{
euint8 resp;
euint16 wc;

if ( wait_ready( iface ) != 0xFF ) {
return 0;
}

if_spiSend( iface, token ); /* Xmit data token */
if ( token != 0xFD ) { /* Is data token */
wc = 0;
do { /* Xmit the 512 byte data block to MMC */
if_spiSend( iface, *buff++);
wc++;
} while (wc<512);

if_spiSend( iface, 0xff); /* CRC (Dummy) */
if_spiSend( iface, 0xff); /* CRC (Dummy) */
resp = if_spiSend( iface, 0xff); /* Reveive data response */
if ( (resp & 0x1F) != 0x05 ) /* If not accepted, return with error */
return 0;
}

return 1;
}

I had to add the wc++ line, otherwise bad things would happen. With this in place the log files seem to open/write/close okay. However when I plug the card into my PC the file appears, but I cannot open it. It shows a legit size and I used a hex editor to verify that the contents appear correct. What else might be going on?

--- In l..., "Michael Anton" wrote:
>
> > -----Original Message-----
> > From: l...
> > [mailto:l...]On Behalf
> > Of drproton2003
> > Sent: Tuesday, July 07, 2009 11:35 PM
> > To: l...
> > Subject: [lpc2000] Re: EFSL and SDHC
> >
> >
> > Well, I found the problem. It looks as though SDHC is only
> > supported on the MCI, not the SPI. I simply did a search for
> > SDHC in all the files. The only hit, other than the
> > initialization routine was in lpc2000_mci.c. From there the
> > only difference I could see is that when reading/writing a
> > sector the address is multiplied by 512 for standard cards
> > and not for SDHC.
>
> Not finding SDHC in comments does not mean much. Most of the
> SDHC support is handled in SD.c, and these routines are usually
> used by all hardware drivers.
>
> The reason that SDHC support didn't work in FIFO mode, is that
> the main reading functions are not called in that interface,
> as it requires something very different. Especially if any
> form of performance is required.
>
> Please take a look at some of my comments on the EFSL Sourceforge
> forums as well, as there are a number of other shortcomings in
> the library that I found some useful workarounds for. Specifically,
> watch out for cache performance issues when writing a lot without
> closing files.
>
>
> >
> > I did a quick bandaid test. I externed CardType from sd.c to
> > lpc2000_sd.c. In the if_readBuf I added the following,
> > likewise in if_writeBuf.
> >
> > if(CardType==1||CardType==2||CardType==4)
> > if_Command(CMDREAD, 512 * address);
> > if(CardType=)
> > if_Command(CMDREAD, address);
> >
> > With this mod it works with the fifo for both SD and SDHC
> > cards. By this I mean that I have successfully made files on
> > both cards, but have no measures of reliability or stability.
>
> That is good news. I thought it should not be too difficult. You may
> want to change it to:
>
> if ( !(CardType & 8) )
> if_Command(CMDREAD, 512 * address);
> else
> if_Command(CMDREAD, address);
>
> to simplify it slightly.
>
> Prior versions were quite reliable after I applied a bunch of patches,
> and fixed some other bugs that I found through my testing. These
> MT versions are supposed to have all of those applied. Alas, many
> new features have been added as well, and as you have found there
> are obviously a number of bugs remaining.
>
> >
> > As to the problems with the non-fifo routines. Here is the
> > function that clocks in the sector:
> >
> > static euint8 rcvr_datablock (
> > hwInterface *iface,
> > euint8 *buff, /* Data buffer to store received data */
> > euint16 btr /* Byte count (must be even number) */
> > )
> > {
> > euint8 token;
> > euint16 retry;
> >
> > retry = LOOP_CNT_100;
> > /* should retry 100ms */
> > do {
> > token = if_spiSend( iface, 0xff );
> > retry--;
> > } while ((token == 0xFF) && retry);
> >
> > if(token != 0xFE) {
> > return 0; /* If not valid data token,
> > retutn with error */
> > }
> >
> > do { /* Receive the data
> > block into buffer */
> > if_spiSend( iface, *buff++ );
> > if_spiSend( iface, *buff++ );
> > } while (btr -= 2);
> > if_spiSend( iface, 0xff); /* Discard CRC */
> > if_spiSend( iface, 0xff); /* Discard CRC */
> >
> > return 1; /* Return with success */
> > }
> >
> > and it calls:
> >
> > euint8 if_spiSend(hwInterface *iface, euint8 outgoing)
> > {
> > euint8 incoming;
> >
> > #if ( HW_ENDPOINT_LPC2000_SPINUM == 0 )
> > S0SPDR = outgoing;
> > while( !(S0SPSR & (1< > > incoming = S0SPDR;
> > #endif
> >
> > #if ( HW_ENDPOINT_LPC2000_SPINUM == 1 )
> > while( !(SPI_STATUS_REG & (1< > > SSPDR = outgoing;
> > while( !(SPI_STATUS_REG & (1< > > incoming = SSPDR;
> > #endif
> >
> > return(incoming);
> > }
> >
> > Seems to me like if_spiSend( iface, *buff++ ); should be
> > something like *buff++=if_spiSend( iface, 0xFF);
>
> What you propose looks correct when comparing to prior versions.
> I don't know how MT would have missed this.
>
> Mike
>

http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/arm_memcards/lpc213x_chanfat_mthomas_20090528.zip

This is a code from Marthin Thomas to interface Chan's FFs to SDHC,
I've tested it, and it works correctly :)

2009/7/8 drproton2003 :
> I've attempted to fix the non-fifo code. I made the fix to the readsector
> function and the card now initializes correctly. However I found a problem
> in the write function as well
>
> static euint8 xmit_datablock (
> hwInterface *iface,
> const euint8 *buff, /* 512 byte data block to be transmitted */
> euint8 token /* Data/Stop token */
> )
> {
> euint8 resp;
> euint16 wc;
>
> if ( wait_ready( iface ) != 0xFF ) {
> return 0;
> }
>
> if_spiSend( iface, token ); /* Xmit data token */
> if ( token != 0xFD ) { /* Is data token */
> wc = 0;
> do { /* Xmit the 512 byte data block to MMC */
> if_spiSend( iface, *buff++);
> wc++;
> } while (wc<512);
>
> if_spiSend( iface, 0xff); /* CRC (Dummy) */
> if_spiSend( iface, 0xff); /* CRC (Dummy) */
> resp = if_spiSend( iface, 0xff); /* Reveive data response */
> if ( (resp & 0x1F) != 0x05 ) /* If not accepted, return with error */
> return 0;
> }
>
> return 1;
> }
>
> I had to add the wc++ line, otherwise bad things would happen. With this in
> place the log files seem to open/write/close okay. However when I plug the
> card into my PC the file appears, but I cannot open it. It shows a legit
> size and I used a hex editor to verify that the contents appear correct.
> What else might be going on?
>
> --- In l..., "Michael Anton" wrote:
>>
>> > -----Original Message-----
>> > From: l...
>> > [mailto:l...]On Behalf
>> > Of drproton2003
>> > Sent: Tuesday, July 07, 2009 11:35 PM
>> > To: l...
>> > Subject: [lpc2000] Re: EFSL and SDHC
>> >
>> >
>> > Well, I found the problem. It looks as though SDHC is only
>> > supported on the MCI, not the SPI. I simply did a search for
>> > SDHC in all the files. The only hit, other than the
>> > initialization routine was in lpc2000_mci.c. From there the
>> > only difference I could see is that when reading/writing a
>> > sector the address is multiplied by 512 for standard cards
>> > and not for SDHC.
>>
>> Not finding SDHC in comments does not mean much. Most of the
>> SDHC support is handled in SD.c, and these routines are usually
>> used by all hardware drivers.
>>
>> The reason that SDHC support didn't work in FIFO mode, is that
>> the main reading functions are not called in that interface,
>> as it requires something very different. Especially if any
>> form of performance is required.
>>
>> Please take a look at some of my comments on the EFSL Sourceforge
>> forums as well, as there are a number of other shortcomings in
>> the library that I found some useful workarounds for. Specifically,
>> watch out for cache performance issues when writing a lot without
>> closing files.
>> >
>> > I did a quick bandaid test. I externed CardType from sd.c to
>> > lpc2000_sd.c. In the if_readBuf I added the following,
>> > likewise in if_writeBuf.
>> >
>> > if(CardType==1||CardType==2||CardType==4)
>> > if_Command(CMDREAD, 512 * address);
>> > if(CardType=)
>> > if_Command(CMDREAD, address);
>> >
>> > With this mod it works with the fifo for both SD and SDHC
>> > cards. By this I mean that I have successfully made files on
>> > both cards, but have no measures of reliability or stability.
>>
>> That is good news. I thought it should not be too difficult. You may
>> want to change it to:
>>
>> if ( !(CardType & 8) )
>> if_Command(CMDREAD, 512 * address);
>> else
>> if_Command(CMDREAD, address);
>>
>> to simplify it slightly.
>>
>> Prior versions were quite reliable after I applied a bunch of patches,
>> and fixed some other bugs that I found through my testing. These
>> MT versions are supposed to have all of those applied. Alas, many
>> new features have been added as well, and as you have found there
>> are obviously a number of bugs remaining.
>>
>> >
>> > As to the problems with the non-fifo routines. Here is the
>> > function that clocks in the sector:
>> >
>> > static euint8 rcvr_datablock (
>> > hwInterface *iface,
>> > euint8 *buff, /* Data buffer to store received data */
>> > euint16 btr /* Byte count (must be even number) */
>> > )
>> > {
>> > euint8 token;
>> > euint16 retry;
>> >
>> > retry = LOOP_CNT_100;
>> > /* should retry 100ms */
>> > do {
>> > token = if_spiSend( iface, 0xff );
>> > retry--;
>> > } while ((token == 0xFF) && retry);
>> >
>> > if(token != 0xFE) {
>> > return 0; /* If not valid data token,
>> > retutn with error */
>> > }
>> >
>> > do { /* Receive the data
>> > block into buffer */
>> > if_spiSend( iface, *buff++ );
>> > if_spiSend( iface, *buff++ );
>> > } while (btr -= 2);
>> > if_spiSend( iface, 0xff); /* Discard CRC */
>> > if_spiSend( iface, 0xff); /* Discard CRC */
>> >
>> > return 1; /* Return with success */
>> > }
>> >
>> > and it calls:
>> >
>> > euint8 if_spiSend(hwInterface *iface, euint8 outgoing)
>> > {
>> > euint8 incoming;
>> >
>> > #if ( HW_ENDPOINT_LPC2000_SPINUM == 0 )
>> > S0SPDR = outgoing;
>> > while( !(S0SPSR & (1< >> > incoming = S0SPDR;
>> > #endif
>> >
>> > #if ( HW_ENDPOINT_LPC2000_SPINUM == 1 )
>> > while( !(SPI_STATUS_REG & (1< >> > SSPDR = outgoing;
>> > while( !(SPI_STATUS_REG & (1< >> > incoming = SSPDR;
>> > #endif
>> >
>> > return(incoming);
>> > }
>> >
>> > Seems to me like if_spiSend( iface, *buff++ ); should be
>> > something like *buff++=if_spiSend( iface, 0xFF);
>>
>> What you propose looks correct when comparing to prior versions.
>> I don't know how MT would have missed this.
>>
>> Mike
>>

--
Miguel Angel Ajo Pelayo
http://www.nbee.es
+34 91 120 1798
+34 636 52 25 69
skype: ajoajoajo

Memfault Beyond the Launch