Forum: Mikrocontroller und Digitale Elektronik SD Karte Initialisieren -> Error


von Christian F. (christianf)


Lesenswert?

Moin,

leider konnten mir die vorhanden Threads nicht helfen.

Und zwar möchte ich ( wie so viele andere ) eine SD Karte betreiben.

Ich benutze dazu einen Spartan 6 inkl. Microblaze Core und SPI 
interface.

Soweit scheint auch alles zu funktionieren, nur bei der initialisierung 
hakt es.

Ich betreibe eine SD V2.0 Karte von SanDisk mit 2GB Kapazität und mein 
Programm ist nur für diese aufgelegt.

Auch fahre ich das Ganze direkt mit 2,5Mhz, da meines Wissens nur die 
MMC Karte eine 400Khz-Initialisierung benötigt.

Ich haben mich an den Code von einigen Vorgänger orientiert, also nicht 
wundern.

Folgende Fehlermeldung erhalte ich in meinem Terminal.
1
starting  SD initialization
2
SDCard Hardware initialized.
3
Go IDLE mode ...
4
card response : 0x1
5
Card is in IDLE mode
6
leave IDLE mode
7
card response : 0xfc
8
card response : 0xe1
9
card response : 0xe1
10
card response : 0xe1
11
...
12
Error: card didn't left idle mode

Zur info:

"leave IDLE mode" ist ein CMD55 + ACMD41 ohne HCS bit.

Zum besseren Verständnis poste ich Euch nochmal die ini.c

(nicht wundern, ist gerade eine Baustelle und einiges auskommentiert)
1
Xuint8 sd_init(void)
2
  {
3
    int Stat;
4
    int j;
5
    int n;
6
    Xuint8 Card_Response;
7
    Xuint8  ocr[4];
8
    int count;
9
10
    spi_init();                                    // init for SPI XPS Core
11
12
    delay(500);                                    // wait some time after PowerUP
13
14
    sd_send_cmd_no_cs();                              // send 8 clock sets for sd card
15
16
    printf("SDCard Hardware initialized.\n");
17
18
    /* [] Start Initialization [] */
19
    printf("Go IDLE mode ... \n");
20
21
    j = 100;
22
23
    do
24
    {
25
      Card_Response = sd_send_cmd(CMD0,0x00,0x00,0x00,0x00);
26
      printf("card response : 0x%x \n", Card_Response);
27
      if (Card_Response == 1)
28
      {
29
        printf("Card is in IDLE mode\n");
30
        //if (sd_send_cmd(CMD8, 0x0000,0x01AA) == 1)
31
        //{
32
          //for (n = 0; n < 4; n++)
33
          //{
34
          //  ocr[n] = spi_read_byte();                      // Get trailing return value of R7 resp
35
          //}
36
          //if (ocr[2] == 0x01 && ocr[3] == 0xAA)                // The card can work at vdd range of 2.7-3.6V
37
          //{
38
              Card_Response = 1;
39
              count = SD_INIT_TIMEOUT;
40
              printf("leave IDLE mode\n");
41
              while(Card_Response)                    // leave idle state
42
              {
43
                Card_Response = sd_send_cmd(CMD55,0x00,0x00,0x00,0x00);
44
                Card_Response = sd_send_cmd(ACMD41,0x00,0x00,0x00,0x00);// no need SD HC support
45
                printf("card response : 0x%x \n", Card_Response);
46
                if(!(--count)|!Card_Response)
47
                    {
48
                  if(!Card_Response)
49
                  {
50
                    printf("card left idle mode\n");
51
                    Card_Response = sd_send_cmd(CMD16,0x00,0x00,0x02,0x00);// force block size to 512bytes for FAT
52
                    Stat = 1;                     // identifier for correct sd_init
53
                    return Stat;
54
55
                  }
56
                  else
57
                  {
58
                    Stat = 3;
59
                    return Stat;
60
                  }
61
62
                    }
63
              }
64
          //}
65
        //}
66
67
      }
68
      else { j--; }
69
70
    }
71
    while(j>0);
72
73
    Stat = 2 ;
74
    return Stat;
75
76
  } // end sd_init

Beim debuggen erhalte ich von CMD55 : 5 als response (?!)

und von ACMD : 225 oder dergleichen.

Die Frage ist nun, mache ich was im Initialisierungsflow etwas falsch 
oder könnte es an meinen low lvl treibern liegen, also spi_read & 
spi_send_byte.


Gruss !

von Tomas K. (Firma: tktronic) (tktronic)


Lesenswert?

Hi,

probier mal so etwas hier:


uint8 MMC_Init (void)
{
    uint16 Timeout = 0;
    uint8 a, b;
    uint8 cmd[6];
    // bit 6 is set in cmd's
  cmd[0] = 0x40; // cmd0
  cmd[1] = 0;
  cmd[2] = 0;
  cmd[3] = 0;
  cmd[4] = 0;
  cmd[5] = 0x95; // after that CRC is ignored

    for(a=0;a<255;a++){  nop();  };
  // Init MMC/SD-Karte in SPI mode by sending 74+ clocks to card
  for (b = 0;b<0x0f;b++)
    MMC_WriteByte(0xff);

  for(a=0;a<255;a++){  nop();  };

    Timeout = 0;
    a = MMC_WriteCommand (cmd, 1);
    // send CMD0, ignore 0 (empty slot) or 0xff (card not ready)
    // most cards return 0x01, Kingston 512MB 0xf1
  while((a == 0xff) || (a == 0x00))
  {
    a = MMC_WriteCommand (cmd, 1);
        if (Timeout > 200)
      return(1);
        Timeout++;
  }
  // CMD1 to card, cards should clear all bits in response when ready
    Timeout = 0;
  cmd[0] = 0x41;  // Cmd1
  cmd[5] = 0xFF;
    a = MMC_WriteCommand (cmd, 1);
  while( (a & 0x01) > 0 )
  {
        a = MMC_WriteCommand (cmd, 1);
    if (Timeout > 200)
      return(2);
        Timeout++;
  }
  // CMD16 to card, cards should clear all bits in response when ready
    Timeout = 0;
  cmd[0] = 0x50;  // Cmd16
  cmd[3] = 2; // 0x200=512 bytes/block
    a = MMC_WriteCommand (cmd, 1);
  while( a != 0x00)
  {
        a = MMC_WriteCommand (cmd, 1);
    if (Timeout > 200)
      return(3);
        Timeout++;
  }
  return(0);
}

von Jim M. (turboj)


Lesenswert?

> Auch fahre ich das Ganze direkt mit 2,5Mhz, da meines Wissens nur die
> MMC Karte eine 400Khz-Initialisierung benötigt.

Das ist falsch. Auch eine SD-Karte kann nur 400kHz bei der 
Initialisierung, wenn ich die Spec hier korrekt interpretiere - "Bus 
timing is identical to SD mode" - im SD-Modus steht was von 400 kHz bei 
der Initialisierungsphase.

von Christian F. (christianf)


Angehängte Dateien:

Lesenswert?

@ Tomas,  danke ich werd da direkt mal rübergucken und abgleichen.

 @ Jim , bist du dir wirklich sicher? Es gibt viele Posts die das 
bestätigen   und viele die das verneinen :) z.B. siehe Anhang Seite 3/10 
recht Spalte.
Darüber hinaus hat einer mal im Forum auch diese Frage gepostet, ob das 
bei SD überhaupt Pflicht ist und da kam auch die Antwort, dass es nur 
bei MMC der Fall ist.

Ich selber weiß nun ehrlich gesagt nichtmehr so ganz was denn nun 
angesagt ist.

Wegen meinem Problem:

Kann es sein, dass bevor ich ACMD41 senden kann ein CMD8 erfolgen muss?

Quelle:

"But if you do not send CMD8, ACMD41 is still closed - no response."
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=50889&start=0

von Mark L. (Firma: TH Köln) (m2k10) Benutzerseite


Lesenswert?

"Until the end of Card Identification Mode the host shall remain at fOD 
frequency because some cards may have operating frequency restrictions 
during the card identification mode."
So steht's in den Specs, hängt wohl letzten Endes von der Karte ab.

Soweit ich das weiß, muss bei Karten ab Spec2.0 ein CMD8 gesendet 
werden, damit die Karte 'weiß', dass der Host zumindest versucht ihr die 
passende Spannung zu geben.

Mark

von Christian F. (christianf)


Lesenswert?

Hi Mark,

Danke dir.

Folgenden Terminalausdruck habe ich mir noch ausgeben lassen:
1
starting  SD initialization
2
3
SDCard Hardware initialized.
4
5
Go IDLE mode ...
6
7
card response CMD0 : 0x1
8
9
Card is in IDLE mode
10
11
leave IDLE mode
12
13
card response CMD55 : 0xf0
14
15
card response ACMD41 : 0xfc
16
17
card response CMD55 : 0x5
18
19
card response ACMD41 : 0xe1 
20
21
... bis timeout

Was mich ein wenig stutzig macht, ist der erste response vom CMD55.

Kann es angehen, dass der Pegel der MISO Leitung von 0xFF auf low geht 
und der Response quasi der Übergang ist? danach kommt 0x05 also illegal 
command, was die Theorie des fehlenden CMD8 unterstützt :).

EDIT:

Habe das gerade in der Spezifikation gefunden:

It is mandatory for the host compliant to Physical Spec Version 2.00
to send CMD8 before ACMD41.

Also:

() CS High
() Dummyclocks
() CMD 0 -> response : 1 --> IDLE MODE
() CMD 8 -> response : 1 -> Trailerbit [2] & [3] == 0x1AA ? --> passt
while response ACMD41 == 1
() CMD55 -> response : "ignored"
() ACMD41-> response : 0 --> left IDLE MODE
() CMD16 mit 0x00000200 als Trailer für 512 block size (FAT)

fertig?

von Christian F. (christianf)


Lesenswert?

Mh.

Nun habe ich das Problem, dass ich anscheinend das erste Byte vom CMD8 
response also ein R1 mit 0x01 nicht richtig erwische :

1
starting  SD initialization
2
SDCard Hardware initialized.
3
Go IDLE mode ...
4
card response CMD0 : 0x1
5
Card is in IDLE mode
6
card response CMD8 : 0xc1
7
card response CMD0 : 0xf0
8
card response CMD0 : 0xfc
9
card response CMD0 : 0x5
10
card response CMD0 : 0xc1
11
card response CMD0 : 0xf0
12
card response CMD0 : 0xfc
13
card response CMD0 : 0x5
14
card response CMD0 : 0xc1
15
card response CMD0 : 0xf0
16
Error: variable j expired
Da der CMD8 =/= 0x01 ist springt er nochmal "hoch" in den CMD0 send und 
macht wirres Zeug.

wobei 0xC1 ja wäre:
11000001

von Mark L. (Firma: TH Köln) (m2k10) Benutzerseite


Lesenswert?

Ich warte bei CMD8(bzw. überall), bis bei der Antwort das MSB=0 ist, 
erst dann kommt eine korrekte (R7-)Response.

Um die Korrektheit der Übertragung sicher zu stellen, gibt's da die 
Möglichkeit mit dem Check-Pattern (meist 0xAA). Ich fand's immer 
hilfreich, mir die gesamte Antwort auszugeben und das Check-Pattern zu 
überprüfen. Stimmt das auch mit geändertem Wert, ist die SPI-Ansteuerung 
prinzipiell in Ordnung.

Mark

von Christian F. (christianf)


Angehängte Dateien:

Lesenswert?

Hi Mark.

also meine "Lesefunktion" schaut so aus:
1
  Xuint8   spi_read_byte()
2
  {
3
4
    Xuint8 Return = 0;
5
6
    Xuint8 Counter;
7
8
    for(Counter=0;Counter<=8;Counter++)
9
    {
10
      Return = spi_send_byte(0xFF);
11
12
      if(Return!=0xFF)
13
      {
14
        return Return;
15
        }
16
      }
17
18
    return Return;
19
20
  }
D.h. ich schicke nach einem Command mittels der spi_read_byte funktion 
noch solange dummy daten heraus, bis ich ein response erhalte was =/= 0 
ist.

Siehe Scope Bild.

Oben die MOSI Leitung
in der Mitte die CLK
Unten ist die MISO Leitung.

Nach einem Dummysend (nach dem CRC) erfolgt 0xC1 auf der MISO - Leitung.

Wie meinst du das mit dem Checkpattern?

GrusS !

Gruss !

von Christian F. (christianf)


Angehängte Dateien:

Lesenswert?

Mh komisch komisch.

Ich habe nun
1
if(Return!=0xFF)
2
      {
3
        return Return;
4
        }

abgeändert in
1
// SPI_MSB_MASK == 0x80
2
if((Return&SPI_MSB_Mask)==0)
3
      {
4
        return Return;
5
        }

Und irgendwie verschiebt sich das Ganze nur.

Der erste Response ist immer noch 0xC1.

Das Skopebild zeigt CMD0 mit dieser "read" Funktion.

Scheint alles zu funktionieren..

von Mark L. (Firma: TH Köln) (m2k10) Benutzerseite


Lesenswert?

Christian F. schrieb:
> ... bis ich ein response erhalte was =/= 0
> ist.
Im Code steht aber !=0xFF ;-). Ist aber falsch für das Response-Byte, 
dass ist immer nur gültig, wenn das MSB=0 ist. MSB=1 heißt, Karte ist 
beschäftigt, Rest der Bits nutzlos.
1
if (return&0x80 == 0)
 wäre vielleicht passender. Die Routine sieht aber eh' so aus, als wäre 
sie nur für R1 geeignet. Wie empfängst du die Bytes einer R7-Response??

Das Check-Pattern ist Teil von CMD8 (Byte vor CRC) und wird unverändert 
in der R7-Response zurückgesendet. Die 'vorgefertigten' Commands in 
Beschreibungen haben hier meist 0xAA und die passende CRC dafür. Hat 
einfach den Zweck, die Kommunikation zu überprüfen. Kommt das Pattern 
korrekt zurück funktioniert der Austausch Befehl zu Antwort zumindest 
und Probleme liegen woanders. Kommt das Pattern nicht korrekt zurück, 
gibt's ein Problem mit Command-senden und Response-empfangen.

Mark

von Christian F. (christianf)


Angehängte Dateien:

Lesenswert?

Ohne spammen zu wollen, hier nochmal der Ausdruck des Skopes bei dem ich 
solange Dummybytes sende bis die response ein MSB von [0] aufweist.

Damit verschiebe ich dennoch nur das Problem, denn wie zu erkennen ist 
ist nach einem Dummysend der erste Response immer noch 0xC1.

Gruss !

EDIT:

jetzt erst deine Antwort gelesen.

Ich habe den Code geändert auf
1
// SPI_MSB_MASK == 0x80
2
if((Return&SPI_MSB_Mask)==0)
3
      {
4
        return Return;
5
        }

s.o. :)

Und der Ablauf des CMD8 (Ausschnitt aus dem Code oben, nur mittlerweile 
leicht abgeändert):
1
Card_Response = sd_send_cmd(CMD8,0x00,0x00,0x01,0xAA);
2
        printf("card response CMD8 : 0x%x \n", Card_Response);
3
        if (Card_Response == 1)
4
        {
5
          spi_SlaveSelect();
6
          for (n = 0; n < 4; n++)
7
          {
8
            ocr[n] = spi_read_byte();                      // Get trailing return value of R7 resp
9
10
          }
11
          spi_SlaveDeselect();
12
          if (ocr[2] == 0x01 && ocr[3] == 0xAA)                // The card can work at vdd range of 2.7-3.6V
13
          {

d.h. ich sende solange dummybtes bis MSB == 0 ist.
Dann springe ich in die for schleife.
-> setze CS low (nach einem CMD senden und erfolgreichem receive ist 
CS->HIGH)

nun schick ich wieder dummydaten und empfange dann byte per byte des R7.

Allerdings fällt mir gerade ein das ich bei der spi read funktion auch 
auf MSB == 0 polle und das ist ja bei dem R7 response evtl. nicht immer 
der Fall z.B bei dem 0xAA byte.

Nevermind, denn bis dahin komme ich ja garnicht, da Response CMD8 == 1 
schon nicht erfolgt.

von Mark L. (Firma: TH Köln) (m2k10) Benutzerseite


Lesenswert?

Christian F. schrieb:
> Der erste Response ist immer noch 0xC1.

Du gibst der Karte ja auch nur 8(!) Versuche. Für einen Timeout 
vielleicht ein Wenig knapp. Deine For-Schleife läuft so ab: Versuch 8x 
eine gültige Antwort zu bekommen sonst nimm, was grad da ist. Und das 
ist dann halt 0xC1.

Vielleicht lässt du für die ersten Versuche mal alles solange warten, 
bis eine gültige Antwort mit MSB=0 kommt ohne Abbruch, den siehst du ja, 
wenn nix kommt.

Mark

von Christian F. (christianf)


Lesenswert?

Hi Mark,

Ja das stimmt. Allerdings frage ich mich wieso beim CMD0 es nach 1x 
Dummybyte senden mit Dummyresponse, sofort die richtige Antwort kommt ( 
siehe Skopebild 1 ).

Und die Karte reagiert ja nach/mit dem zweiten Dummybyte.

Im übrigen hatte ich das eben gerade versucht :).

Ich habe den Erwartungswert 0x01 vorgegeben und dann
1
while(response!=Erwartet)
2
{
3
response = spi_read_byte;
4
}

nach 20sek kam immer noch nichts.

Von der Sache her kann ich doch so vorgehen:

() send CMD8
() nun gucke ich mir das erste Byte an
() wenn das 0x01 ist, lese ich den Trailer(R7) aus und schaue ob a) der 
Voltagebereich stimmt und b) das Checkpattern von 0xAA.
() dann weiter im Text.

Wie gesagt, ich erhalte kein R1 als erstes Byte des CMD8 responses.

Gruss

von Christian F. (christianf)


Lesenswert?

Habe gerade zufällig im Forum gefunden, dass einer ein ähnliches Problem 
hat.

Und zwar "Oli"

Beitrag "SD Karte keine Antwort auf CMD0 -XC161"

Sein Kommentar:
1
Natürlich wird dann CMD1 wieder und wieder gesendet...
2
Die Antworten von der Karte sind immer: 0xC1 0xF0  0xFC  0x05
3
also immer die gleichen und halt 100mal....

Meine Console :
1
starting  SD initialization
2
SDCard Hardware initialized.
3
Go IDLE mode ...
4
card response CMD0 : 0x1
5
Card is in IDLE mode
6
card response CMD8 : 0xc1
7
card response CMD0 : 0xf0
8
card response CMD0 : 0xfc
9
card response CMD0 : 0x5
10
card response CMD0 : 0xc1
11
card response CMD0 : 0xf0
12
card response CMD0 : 0xfc
13
card response CMD0 : 0x5
14
card response CMD0 : 0xc1
15
card response CMD0 : 0xf0
16
Error: variable j expired
Er schickt CMD1, will aus dem IDLE Mode also raus. Dennoch erhält er den 
gleichen komischen Fehler:

CMD0 funktiniert einwandfrei
alles andere mit Fehlern.

Gruss

von Mark L. (Firma: TH Köln) (m2k10) Benutzerseite


Lesenswert?

Das ist das blöde an Foren, dass sich die Antworten überschneiden 
(passiert gerade wieder ;-)

Wo ist die (korrekte) CRC bei CMD8???
0x48, 0x00, 0x00, 0x01, 0xAA, 0x87 ist das vollständige CMD8 (mit 
Check-Pattern 0xAA). Dein Code verwendet hier auch 0x95, das gibt immer 
einen CRC-Fehler zurück, also 0x09, nicht 0x01.

Das MSB=0 gilt immer für die gesamte antwort, nicht für jedes Byte. Bei 
R7 musst du nur warten, bis ein Byte mit MSB=0 ankommt dann den Rest 
'blind' empfangen.

Christian F. schrieb:
> Und die Karte reagiert ja nach/mit dem zweiten Dummybyte.
Das Busy-Flag hat schon seinen Sinn. Je nach Karte und je nach Befehl 
werden andere Zeiten benötigt.

Zur (aktuell) letzten Antwort von dir:
müsste die CRC sein, daher kein 0x01 (s.o.)
R1 ist ja nur das Datenformat des ersten Antwortbytes bei den meisten 
Commands, alles unter 0x80 ist gültig, auch wenn's eine Fehlermeldung 
ist.
SD-V1-Karten erkennt man bspw. am 'illegal command' bei CMD8(R1=0x05), 
muss man nur ggf. berücksichtigen und trotz 'Fehler' weitermachen.

Auf mich hat das erstmal etwas chaotisch gewirkt. Mal ist etwas ein 
Fehler, mal ein Hinweis auf eine Version.

Grüße

von Christian F. (christianf)


Angehängte Dateien:

Lesenswert?

ALSO.

Es scheint zu gehen :-).

Es lag wirklich daran, dass ich nachdem die Karte in IDLE Mode gegangen 
ist sofort angefangen habe den nächsten CMD zu schicken. In diesem Fall 
CMD8.

Die Karte möchte jedoch erstmal ein paar dummybytes haben.

Ich habe nun nachdem er im IDLE Mode gelandet ist 10x Dummybytes 
gesendet und DANN erst den CMD8 Command.

Er antwortet mit 0x01, sodass ich den Trailer(R7) auswerten kann.

Anbei das Scopebild.

Gruss !

EDIT:

jetzt wieder erst deine Antwort gelesen :-/.

Also die CRC war 0x87.

Code:
1
Xuint8  sd_send_cmd(Xuint8 Command,Xuint8 ParameterA, Xuint8 ParameterB,Xuint8 ParameterC,Xuint8 ParameterD)
2
  {
3
    Xuint8 Dummyresponse;
4
    Xuint8 response;
5
6
    spi_SlaveSelect();                                // CS -> LOW
7
8
    delay(50);                                    // wait some CLKs for stable CS Line
9
10
        Dummyresponse = spi_send_byte(0x40 | Command);                //send the command
11
12
        Dummyresponse = spi_send_byte(ParameterA);                          //send the MSB of ParamX
13
14
        Dummyresponse = spi_send_byte(ParameterB);                             //send the LSB of ParamX
15
16
        Dummyresponse = spi_send_byte(ParameterC);                          //send the MSB of ParamY
17
18
        Dummyresponse = spi_send_byte(ParameterD);                             //send the LSB of ParamY
19
20
        switch(Command)
21
        {
22
          case CMD8:
23
            //when sending the IF cond (CMD8) we must always send
24
            //the correct CRC
25
            Dummyresponse = spi_send_byte(0x87);
26
            break;
27
28
          case CMD0:
29
            //CMD0 = 0x95 CRC
30
            Dummyresponse = spi_send_byte(0x95);
31
            break;
32
33
          default:
34
            //for all other commands, CRC is ignored in SPI mode.
35
            Dummyresponse = spi_send_byte(0xFF);
36
            break;
37
        }
38
39
     response = spi_read_byte();                           // read the SD response
40
41
42
    spi_SlaveDeselect();                               // CS -> HIGH
43
44
    return response;
45
  }

Der Fehler war wohl s.o.

Ich lese nun mal R7 aus und gucke ob Checkpattern und Voltagebit passen.

von Christian F. (christianf)


Lesenswert?

Tja geht das Eine, meckert das Andere herum :).

Jedenfalls ist der Trailer vom CMD8 response = 0x1 sowie 0xAA.

Danach möchte ich jedoch den IDLE Mode verlassen.

Allerdings "spuckt" die Karte dann nicht 0x01 aus und das solange bis 
0x00 steht sondern:
1
starting  SD initialization
2
SDCard Hardware initialized.
3
Go IDLE mode ...
4
card response CMD0 : 0x1
5
Card is in IDLE mode
6
card response CMD8 Byte 1/5 : 0x1
7
card response CMD8 Byte 4/5 : 0x1
8
card response CMD8 Byte 5/5 : 0xaa
9
leave IDLE mode
10
card response CMD55 : 0x5f
11
card response ACMD41 : 0x5
12
card response CMD55 : 0x5f
13
card response ACMD41 : 0x5
14
card response CMD55 : 0x5f
15
... // 50x versuchen
16
Error: card didn't left idle mode


Mit dem CMD1:

1
starting  SD initialization
2
SDCard Hardware initialized.
3
Go IDLE mode ...
4
card response CMD0 : 0x1
5
Card is in IDLE mode
6
card response CMD8 Byte 1/5 : 0x1
7
card response CMD8 Byte 4/5 : 0x1
8
card response CMD8 Byte 5/5 : 0xaa
9
leave IDLE mode
10
card response CMD1 : 0x7f
11
card response CMD1 : 0x1
12
card response CMD1 : 0x1
13
card response CMD1 : 0x1
14
card response CMD1 : 0x0
15
card left idle mode
16
card response CMD16 : 0x0
17
sd_init complete

Macht das eigentlich sinn vor jedem command einmal dummy bytes zu 
schicken?

Ich merke gerade, dass es sich positiv auswirkt.

Gruss

von Christian F. (christianf)


Lesenswert?

Antwort:

ja es bringt etwas :)
1
starting  SD initialization
2
SDCard Hardware initialized.
3
Go IDLE mode ...
4
card response CMD0 : 0x1
5
Card is in IDLE mode
6
card response CMD8 Byte 1/5 : 0x1
7
card response CMD8 Byte 4/5 : 0x1
8
card response CMD8 Byte 5/5 : 0xaa
9
leave IDLE mode
10
card response CMD55 : 0x1
11
card response ACMD41 : 0x1
12
card response CMD55 : 0x1
13
card response ACMD41 : 0x1
14
card response CMD55 : 0x1
15
card response ACMD41 : 0x0
16
card left idle mode
17
card response CMD16 : 0x0
18
sd_init complete

Damit wäre meine Init ja fertig.

Nun mal schauen wie ich da Daten raufbekomme :)

Gruss !

von Christian F. (christianf)


Lesenswert?

Dennoch mal eine Frage in die Runde.

Habt ihr in euer Realisierung das ebenfalls so gemacht?

Ich habe das nun runtergebrochen und sobald ich vor dem Command ein 
Dummybyte sende funktioniert es.

Ohne Dummybyte, keine Chance. Woran liegt das?

Hier der Codeschnipsel :
1
Xuint8  sd_send_cmd(Xuint8 Command,Xuint8 ParameterA, Xuint8 ParameterB,Xuint8 ParameterC,Xuint8 ParameterD)
2
  {
3
    Xuint8 Dummyresponse;
4
    Xuint8 response;
5
6
    spi_SlaveSelect();                                // CS -> LOW
7
    delay(50);                                    // wait some CLKs for stable CS Line
8
9
      spi_send_byte(0xFF);                            // send 1x Dummybytes
10
11
        Dummyresponse = spi_send_byte(0x40 | Command);                //send the command
12
13
        Dummyresponse = spi_send_byte(ParameterA);                          //send the MSB of ParamX
14
15
        Dummyresponse = spi_send_byte(ParameterB);                             //send the LSB of ParamX
16
17
        Dummyresponse = spi_send_byte(ParameterC);                          //send the MSB of ParamY
18
19
        Dummyresponse = spi_send_byte(ParameterD);                             //send the LSB of ParamY
20
21
... usw usw.

von Mark L. (Firma: TH Köln) (m2k10) Benutzerseite


Lesenswert?

Hab' bei mir mal nachgesehen, ich sende nach jedem Command ein Dummybyte 
mit CS=high. Funktioniert auch.

Grundsätzlich ist die Logik in der Karte fest verdrahtet und benötigt 
das Clocksignal um intern zu schalten.

von Christian F. (christianf)


Lesenswert?

Hi,

Das tu ich auch und es reicht nicht.

<<<< Es funktioniert nicht: >>>>
1
Xuint8  sd_send_cmd(Xuint8 Command,Xuint8 ParameterA, Xuint8 ParameterB,Xuint8 ParameterC,Xuint8 ParameterD)
2
  {
3
    Xuint8 Dummyresponse;
4
    Xuint8 response;
5
6
    spi_SlaveSelect();                                // CS -> LOW
7
    delay(50);                                    // wait some CLKs for stable CS Line
8
9
10
11
        Dummyresponse = spi_send_byte(0x40 | Command);                //send the command
12
13
        Dummyresponse = spi_send_byte(ParameterA);                          //send the MSB of ParamX
14
15
        Dummyresponse = spi_send_byte(ParameterB);                             //send the LSB of ParamX
16
17
        Dummyresponse = spi_send_byte(ParameterC);                          //send the MSB of ParamY
18
19
        Dummyresponse = spi_send_byte(ParameterD);                             //send the LSB of ParamY
20
21
        switch(Command)
22
        {
23
          case CMD8:
24
            //when sending the IF cond (CMD8) we must always send
25
            //the correct CRC
26
            Dummyresponse = spi_send_byte(0x87);
27
            break;
28
29
          case CMD0:
30
            //CMD0 = 0x95 CRC
31
            Dummyresponse = spi_send_byte(0x95);
32
            break;
33
34
          default:
35
            //for all other commands, CRC is ignored in SPI mode.
36
            Dummyresponse = spi_send_byte(0xFF);
37
            break;
38
        }
39
40
     response = spi_read_byte();                           // read the SD response
41
42
43
    spi_SlaveDeselect();                               // CS -> HIGH
44
45
    return response;
46
  }

<<<< die spi_read_byte funktion dazu(die MSB Abfrage wieder 
auskommentiert, geht bei mir auch ohne):>>>>
1
  Xuint8   spi_read_byte()
2
  {
3
4
    Xuint8 Return = 0;
5
6
    Xuint8 Counter;
7
8
    for(Counter=0;Counter<=8;Counter++)
9
    {
10
      Return = spi_send_byte(0xFF);
11
12
      if(Return!=0xFF)
13
      //if((Return&SPI_MSB_Mask)==0)
14
      {
15
        return Return;
16
        }
17
      }
18
19
    return Return;
20
21
  }

So.

<<<< nun änder ich folgendes >>>>:

Ich füge vor dem ersten Command folgendes ein
1
Xuint8  sd_send_cmd(Xuint8 Command,Xuint8 ParameterA, Xuint8 ParameterB,Xuint8 ParameterC,Xuint8 ParameterD)
2
  {
3
    Xuint8 Dummyresponse;
4
    Xuint8 response;
5
6
    spi_SlaveSelect();                                // CS -> LOW
7
    delay(50);                                    // wait some CLKs for stable CS Line
8
9
      spi_send_byte(0xFF);                            // send 1x Dummybytes
10
11
        Dummyresponse = spi_send_byte(0x40 | Command);                //send the command
12
13
14
... usw. das andere wie gehabt.

gleiche spi_read_byte funktion. >>>>


--> es geht !

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.