I've had a few queries in regards to SD card initialization in SPI
mode.
For anyone who is interested I have included a dump of the SPI activity
during an init. There are two examples, the first with a SANDISK 512M
Ultra, and the second with a generic 128M SD.
The SD & FAT code are written in a Forth that I have written for the
LPC2000s. Since this is not everyones cup of tea, I have included a
simple dump of the activity of the SD interface. Comments are as normal
and bytes that are read are prefixed with "r", those that are written
with "w".
Although it is possible to issue a CMD1 following a CMD0, the SANDISK SD
CARD product manual states that ACMD41 should be used. This avoids
confusion with MMC cards but read what SANDISK have to say in section
5.8. Apparently ACMD1 is an illegal command for the thin cards in SPI mode.
The dummy read at the start of the CMD is just to make sure that the SD
interface is synchronized etc. This is easier than putting dummy reads
at the end of transfers .
One thing that didn't show-up on the 128M cards but did on the 512M was
when I was accessing high memory around 300MBs up. I would find that the
data token response on a read block request was taking a lot longer. I
had to either introduce a delay of 1ms in each loop or increase the
retry counter from 8 to 4000!!! (I am running at 16Mhz SPI rate).
I thought always CMD0 had to be send to reset the card and then CMD1
to activate it.
I haven't seen other guys do it differently too.
But you are beginnning with ACDM41? and then CMD58?
maybe you can send or post your code so I can compare it?
thanks,
Wouter
--- In lpc2000@lpc2..., Peter Jakacki <peterjak@t...> wrote: >
> Look under the SPI section in the sandisk manual. I use ACMD41 as this
> is the recommended method followed by CMD58 to read the OCR. One little
> thing I do different is to pad the start of a CMD with a couple of dummy > reads (same as writing 0xFF). I have implemented
an SD driver and FAT16
> successfully on the 2106 as well as the 2138 and tested this on about 5
> different types of SD cards to date.
>
> BTW, when you power-down the supply just make sure all the SD I/O lines
> are taken down to VSS as well.
>
> *Peter*
> armqamp wrote:
>
> >Hello,
> >
> >I'm trying to make an SD card to work with the lpc2106 and later
want
> >to implement FAT.
> >The problem is I don't get any response of the SD card when I try
to
> >initialize it.
> >
> >Maybe somebody can disover what I'm doing wrong?
> >
> >here is the code:
> >
> >@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
> >
> >void ActivateSD(void){
> >
> > unsigned int ii=0;
> > unsigned char resp, i;
> > unsigned char status;
> >
> > print("Activating SD Card....\n\n");
> >
> > // Turn off SD Card
> > SD_power_off;
> >
> > // Wait for power to really go down
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> >
> > // Turn on SD Card
> > SD_power_on;
> >
> > // Wait for power to really come up
> > for(status = 0; status < 10; ++status)
> > {
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> > }
> >
> >
> >
> >
> >
> > for(i=1; i<; i++){ //try 10 times to wake up the card > >
> > SD_disable; //CS high
> >
> > InitSequence(); //send 80 clocks
> >
> > SD_enable; //CS low
> >
> > SD_SendCommand(CMD0,0,0,0,0); //send Reset command
> >
> > resp = SD_Response();
> > if( resp == 0x01 ){ //wait for R1 response to be 0x01
> > break;
> > }
> > else{
> >
> > }
> >
> > }
> >
> > spiSendByte(0xFF); // Response received, send the required 8
> >clocks after the response to finish up (page 5-6 Sandisk Manual)
> >
> >
> > if(i>10){
> > SD_disable;
> > print("SD activation failed\n");
> > }
> > else{
> > print("SD activation successfully\n");
> >
> > while( resp != 0x00){ //try sending CMD1 until
> >response R1 is 0x00
> > SD_SendCommand(CMD1,0,0,0,0); //activate card initialization process > > resp = SD_Response();
> > spiSendByte(0xFF); //send required 8 clocks
> > if(resp==0x00){ // Ready
> > print("SD successfully activated!!!\n");
> > break;
> > }
> > }
> >
> > if(resp != 0x00){
> > print("Error: ");
> > print("0x"); printnum(16, 8, 0, '0', resp);
print("\n");
> > }
> >
> > }
> > print("\n-------end-----------\n");
> >}
> >
> >
> >unsigned char SD_Response(void) {
> > unsigned char i;
> > unsigned char resp;
> >
> > for(i=0; i<10; i++) {
> > resp = spiGetByte();
> > if(resp != 0xFF) {
> > return resp;
> > }
> > }
> > return 0xFF;
> >}
> >
> >void SD_SendCommand(unsigned char command, unsigned char arg_a,
> >unsigned char arg_b, unsigned char arg_c, unsigned char arg_d) {
> > spiSendByte(command);
> > spiSendByte(arg_a);
> > spiSendByte(arg_b);
> > spiSendByte(arg_c);
> > spiSendByte(arg_d);
> > spiSendByte(0x95); // correct CRC for first command in SPI after
> >that CRC is ignored, so no problem with always sending 0x95
> >}
> >
> >
>
Reply by Peter Jakacki●October 11, 20052005-10-11
Look under the SPI section in the sandisk manual. I use ACMD41 as this
is the recommended method followed by CMD58 to read the OCR. One little
thing I do different is to pad the start of a CMD with a couple of dummy
reads (same as writing 0xFF). I have implemented an SD driver and FAT16
successfully on the 2106 as well as the 2138 and tested this on about 5
different types of SD cards to date.
BTW, when you power-down the supply just make sure all the SD I/O lines
are taken down to VSS as well.
*Peter*
armqamp wrote:
>Hello,
>
>I'm trying to make an SD card to work with the lpc2106 and later
want
>to implement FAT.
>The problem is I don't get any response of the SD card when I try to
>initialize it.
>
>Maybe somebody can disover what I'm doing wrong?
>
>here is the code:
>
>@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
>
>void ActivateSD(void){
>
> unsigned int ii=0;
> unsigned char resp, i;
> unsigned char status;
>
> print("Activating SD Card....\n\n");
>
> // Turn off SD Card
> SD_power_off;
>
> // Wait for power to really go down
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
>
> // Turn on SD Card
> SD_power_on;
>
> // Wait for power to really come up
> for(status = 0; status < 10; ++status)
> {
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
> }
> for(i=1; i<; i++){ //try 10 times to wake up the card
>
> SD_disable; //CS high
>
> InitSequence(); //send 80 clocks
>
> SD_enable; //CS low
>
> SD_SendCommand(CMD0,0,0,0,0); //send Reset command
>
> resp = SD_Response();
> if( resp == 0x01 ){ //wait for R1 response to be 0x01
> break;
> }
> else{
>
> }
>
> }
>
> spiSendByte(0xFF); // Response received, send the required 8
>clocks after the response to finish up (page 5-6 Sandisk Manual)
> if(i>10){
> SD_disable;
> print("SD activation failed\n");
> }
> else{
> print("SD activation successfully\n");
>
> while( resp != 0x00){ //try sending CMD1 until
>response R1 is 0x00
> SD_SendCommand(CMD1,0,0,0,0); //activate card initialization process
> resp = SD_Response();
> spiSendByte(0xFF); //send required 8 clocks
> if(resp==0x00){ // Ready
> print("SD successfully activated!!!\n");
> break;
> }
> }
>
> if(resp != 0x00){
> print("Error: ");
> print("0x"); printnum(16, 8, 0, '0', resp);
print("\n");
> }
>
> }
> print("\n-------end-----------\n");
>}
>unsigned char SD_Response(void) {
> unsigned char i;
> unsigned char resp;
>
> for(i=0; i<10; i++) {
> resp = spiGetByte();
> if(resp != 0xFF) {
> return resp;
> }
> }
> return 0xFF;
>}
>
>void SD_SendCommand(unsigned char command, unsigned char arg_a,
>unsigned char arg_b, unsigned char arg_c, unsigned char arg_d) {
> spiSendByte(command);
> spiSendByte(arg_a);
> spiSendByte(arg_b);
> spiSendByte(arg_c);
> spiSendByte(arg_d);
> spiSendByte(0x95); // correct CRC for first command in SPI after
>that CRC is ignored, so no problem with always sending 0x95
>}
Reply by theothervmax●October 11, 20052005-10-11
--- In lpc2000@lpc2..., "armqamp" <wouter@w...> wrote: >
> I defined the commands like this:
>
> #define CMD0 0x40 // software reset
> #define CMD1 0x41 // brings card out of idle state
> #define CMD2 0x42 // not used in SPI mode
> #define CMD3 0x43 // not used in SPI mode
> #define CMD4 0x44 // not used in SPI mode
> #define CMD5 0x45 // Reserved
> #define CMD6 0x46 // Reserved
> #define CMD7 0x47 // not used in SPI mode
>
> and so on...
> thanks,
>
> Wouter
>
Rest of the code looks good, except for that:
if(i>10){
SD_disable;
print("SD activation failed\n");
}
else{
print("SD activation successfully\n");
}
If "SD_disable" is just setting CS high, you'd better do it every
time after sending command (and getting response), not only if something
failed.
Max
Reply by armqamp●October 11, 20052005-10-11
I defined the commands like this:
#define CMD0 0x40 // software reset
#define CMD1 0x41 // brings card out of idle state
#define CMD2 0x42 // not used in SPI mode
#define CMD3 0x43 // not used in SPI mode
#define CMD4 0x44 // not used in SPI mode
#define CMD5 0x45 // Reserved
#define CMD6 0x46 // Reserved
#define CMD7 0x47 // not used in SPI mode
and so on...
thanks,
Wouter
--- In lpc2000@lpc2..., "theothervmax" <vmax@g...> wrote: >
> --- In lpc2000@lpc2..., "armqamp" <wouter@w...> wrote:
> >
> > Hello,
> >
> > I'm trying to make an SD card to work with the lpc2106 and later
want
> > to implement FAT.
> > The problem is I don't get any response of the SD card when I try
to
> > initialize it.
> >
> > Maybe somebody can disover what I'm doing wrong?
> >
> > here is the code:
> >
> > @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
> >
> > void ActivateSD(void){
> >
> > unsigned int ii=0;
> > unsigned char resp, i;
> > unsigned char status;
> >
> > print("Activating SD Card....\n\n");
> >
> > // Turn off SD Card
> > SD_power_off;
> >
> > // Wait for power to really go down
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> >
> > // Turn on SD Card
> > SD_power_on;
> >
> > // Wait for power to really come up
> > for(status = 0; status < 10; ++status)
> > {
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> > for(ii = 0; ii; ii++);
> > }
> >
> >
> >
> >
> >
> > for(i=1; i<; i++){ //try 10 times to wake up the card > >
> > SD_disable; //CS high
> >
> > InitSequence(); //send 80 clocks
> >
> > SD_enable; //CS low
> >
> > SD_SendCommand(CMD0,0,0,0,0); //send Reset command
> >
> > resp = SD_Response();
> > if( resp == 0x01 ){ //wait for R1 response to be 0x01
> > break;
> > }
> > else{
> >
> > }
> >
> > }
> >
> > spiSendByte(0xFF); // Response received, send the required 8
> > clocks after the response to finish up (page 5-6 Sandisk Manual)
> >
> >
> > if(i>10){
> > SD_disable;
> > print("SD activation failed\n");
> > }
> > else{
> > print("SD activation successfully\n");
> >
> > while( resp != 0x00){ //try sending CMD1 until
> > response R1 is 0x00
> > SD_SendCommand(CMD1,0,0,0,0); //activate card initialization process > > resp = SD_Response();
> > spiSendByte(0xFF); //send required 8 clocks
> > if(resp==0x00){ // Ready
> > print("SD successfully activated!!!\n");
> > break;
> > }
> > }
> >
> > if(resp != 0x00){
> > print("Error: ");
> > print("0x"); printnum(16, 8, 0, '0', resp);
print("\n");
> > }
> >
> > }
> > print("\n-------end-----------\n");
> > }
> >
> >
> > unsigned char SD_Response(void) {
> > unsigned char i;
> > unsigned char resp;
> >
> > for(i=0; i<10; i++) {
> > resp = spiGetByte();
> > if(resp != 0xFF) {
> > return resp;
> > }
> > }
> > return 0xFF;
> > }
> >
> > void SD_SendCommand(unsigned char command, unsigned char arg_a,
> > unsigned char arg_b, unsigned char arg_c, unsigned char arg_d) {
> > spiSendByte(command);
> > spiSendByte(arg_a);
> > spiSendByte(arg_b);
> > spiSendByte(arg_c);
> > spiSendByte(arg_d);
> > spiSendByte(0x95); // correct CRC for first command in SPI after
> > that CRC is ignored, so no problem with always sending 0x95
> > }
> >
> > @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
> >
>
> First, what's the value of "CMD0" ? It must be 0x40.
>
> Cheers,
> Max.
>
Reply by theothervmax●October 11, 20052005-10-11
--- In lpc2000@lpc2..., "armqamp" <wouter@w...> wrote: >
> Hello,
>
> I'm trying to make an SD card to work with the lpc2106 and later
want
> to implement FAT.
> The problem is I don't get any response of the SD card when I try
to
> initialize it.
>
> Maybe somebody can disover what I'm doing wrong?
>
> here is the code:
>
> @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
>
> void ActivateSD(void){
>
> unsigned int ii=0;
> unsigned char resp, i;
> unsigned char status;
>
> print("Activating SD Card....\n\n");
>
> // Turn off SD Card
> SD_power_off;
>
> // Wait for power to really go down
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
>
> // Turn on SD Card
> SD_power_on;
>
> // Wait for power to really come up
> for(status = 0; status < 10; ++status)
> {
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
> for(ii = 0; ii; ii++);
> }
> for(i=1; i<; i++){ //try 10 times to wake up the card
>
> SD_disable; //CS high
>
> InitSequence(); //send 80 clocks
>
> SD_enable; //CS low
>
> SD_SendCommand(CMD0,0,0,0,0); //send Reset command
>
> resp = SD_Response();
> if( resp == 0x01 ){ //wait for R1 response to be 0x01
> break;
> }
> else{
>
> }
>
> }
>
> spiSendByte(0xFF); // Response received, send the required 8
> clocks after the response to finish up (page 5-6 Sandisk Manual)
> if(i>10){
> SD_disable;
> print("SD activation failed\n");
> }
> else{
> print("SD activation successfully\n");
>
> while( resp != 0x00){ //try sending CMD1 until
> response R1 is 0x00
> SD_SendCommand(CMD1,0,0,0,0); //activate card initialization process
> resp = SD_Response();
> spiSendByte(0xFF); //send required 8 clocks
> if(resp==0x00){ // Ready
> print("SD successfully activated!!!\n");
> break;
> }
> }
>
> if(resp != 0x00){
> print("Error: ");
> print("0x"); printnum(16, 8, 0, '0', resp);
print("\n");
> }
>
> }
> print("\n-------end-----------\n");
> }
> unsigned char SD_Response(void) {
> unsigned char i;
> unsigned char resp;
>
> for(i=0; i<10; i++) {
> resp = spiGetByte();
> if(resp != 0xFF) {
> return resp;
> }
> }
> return 0xFF;
> }
>
> void SD_SendCommand(unsigned char command, unsigned char arg_a,
> unsigned char arg_b, unsigned char arg_c, unsigned char arg_d) {
> spiSendByte(command);
> spiSendByte(arg_a);
> spiSendByte(arg_b);
> spiSendByte(arg_c);
> spiSendByte(arg_d);
> spiSendByte(0x95); // correct CRC for first command in SPI after
> that CRC is ignored, so no problem with always sending 0x95
> }
>
> @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
>
First, what's the value of "CMD0" ? It must be 0x40.
Cheers,
Max.
Reply by armqamp●October 11, 20052005-10-11
Hello,
I'm trying to make an SD card to work with the lpc2106 and later want
to implement FAT.
The problem is I don't get any response of the SD card when I try to
initialize it.
Maybe somebody can disover what I'm doing wrong?
here is the code:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void ActivateSD(void){
unsigned int ii=0;
unsigned char resp, i;
unsigned char status;
print("Activating SD Card....\n\n");
// Turn off SD Card
SD_power_off;
// Wait for power to really go down
for(ii = 0; ii; ii++);
for(ii = 0; ii; ii++);
for(ii = 0; ii; ii++);
for(ii = 0; ii; ii++);
// Turn on SD Card
SD_power_on;
// Wait for power to really come up
for(status = 0; status < 10; ++status)
{
for(ii = 0; ii; ii++);
for(ii = 0; ii; ii++);
for(ii = 0; ii; ii++);
for(ii = 0; ii; ii++);
}
for(i=1; i<; i++){ //try 10 times to wake up the card
void SD_SendCommand(unsigned char command, unsigned char arg_a,
unsigned char arg_b, unsigned char arg_c, unsigned char arg_d) {
spiSendByte(command);
spiSendByte(arg_a);
spiSendByte(arg_b);
spiSendByte(arg_c);
spiSendByte(arg_d);
spiSendByte(0x95); // correct CRC for first command in SPI after
that CRC is ignored, so no problem with always sending 0x95
}