Forum: Mikrocontroller und Digitale Elektronik SD Karte 4 Bit Modus CRC Datencheck


von fpga_thorben (Gast)


Lesenswert?

Hi forum,

ich hab ne frage zum crc check von der sd karte im 4 bit modus.

falls der crc check failt, wie erhalte ich von der karte eine anntwort, 
dass der crc fehlerhaft war?
ich schicke die daten vom block rüber, danach den crc, mein controller 
wartet (3 mal), solange bis die  erste datenleitung wieder 1 ist und 
wenn ich den beschriebenen block daten lesen will, lese ich nur nullen.

ich hab die realisierung des crc's jeder datenleitung selbst in c 
realisiert, weshalb ich vermute, dass da irgendwo ein fehler ist und 
würde gern von der karte wissen, ob denn beim schreiben der daten-crc16 
fehlerhaft war.

hab in der sd karten spec nur ein 'crc error status' für einen command 
gefunden, nicht fürs datenschreiben.


würde mich um tipps und info sehr freuen.


vielen dank
thorben

von Jim M. (turboj)


Lesenswert?

fpga_thorben schrieb:
> hab in der sd karten spec nur ein 'crc error status' für einen command
> gefunden, nicht fürs datenschreiben.

Probier mal aus ob der nicht auch bei CRC Fehlern in Datenblöcken 
gesetzt wird.

Bei SD Karten kann man auch mit ACMD22 die Anzahl der geschriebenen 
Blöcke prüfen.

von Brue W. (brue)


Lesenswert?

Hi,

Es gibt zwei CRCs, eine fuer die Kommandos und eine fuer die Daten.
Wenn du ein Schreibkommando absetzt bekommst du zunächst eine Response 
der Karte. Wenn nicht, dann war die CRC des Kommandos falsch oder das 
Kommando Illegal. In so einem Fall liest man ACMD13 das SD Status 
Register und überprüft dort welche Fehlerbits gesetzt sind.

Ist die Response der Karte aber gekommen und OK, schickt man die Daten. 
Nach der Daten schickt man die CRC. Danach kommt von der Karte ein crc 
status token dass einem mitteilt ob die Daten richtig empfangen wurden 
oder nicht. Falls sie das wurden, kann die Karte danach busy werden um 
schlieslich die Daten zu programmieren.

Gruss

von fpga_thorben (Gast)


Lesenswert?

ich hätte noch eine frage.

berechne ich den crc16 vom zu sendeten 512 langen array und übertrage 
dann den crc über die 4 leitungen oder muss ich für jede datenleitung 
einen eigenen crc berechnen und diesen übertragen?

von Brue W. (brue)


Lesenswert?

Fuer jede Datenleitung separat auf der jeweiligen leitung.
Das steht aber alles in der SD spec und ist eigentlich gut erklaert.

von fpga_thorben (Gast)


Angehängte Dateien:

Lesenswert?

ich beschreibe nochmal kurz wie ich es mache:

ich sende 512 bytes mit dem inhalt 255.
danach berechne ich den crc16 für jede datenleitung, d. h. ein crc16 
über ein 128 byte langes array, wo nur 1 stehen.
ich erhalte für jede datenleitung den berechneten crc16 wert 60841, was 
in hexadecimal EDA9 entspricht.

d. h.
dat0: 0b1110110110101001 (pin0)
dat1: 0b1110110110101001 (pin1)
dat2: 0b1110110110101001 (pin2)
dat3: 0b1110110110101001 (pin3)


d. h. ich sende sozusagen, wenn man es quer anschaut: FFF0FF0FF0F0F00F 
rüber.

meine funktion, die 4 bits sendet, erhält einen 8 bit wert und schreibt 
ihn auf den pins parralel, zuerst die 4 MSB bits, dann die 4 LSB bits
der crc wird nach den daten folgend ausgegeben:

[c]
   for(j=0;j<16;j++)
   {

     SD_CLK_LOW;

      if(j < 8)
      {

        SD_DAT_WRITE((alt_u8)(crc_send_buffer_MSB >> 28) & 0x0F);
        printf("%u ", (unsigned int)(crc_send_buffer_MSB >> 28) & 0x0F);
        crc_send_buffer_MSB <<= 4;

      }

      else
      {

        SD_DAT_WRITE((alt_u8)(crc_send_buffer_LSB >> 28) & 0x0F);
        printf("%u ", (unsigned int)(crc_send_buffer_LSB >> 28) & 0x0F);
        crc_send_buffer_LSB <<= 4;

      }

     SD_CLK_HIGH;

   }
[c]

wenn ich es mir auf der console anschaue, scheint alles okay zu sein.
der crc ist korrekt, trotzdem ist das gelesene array leer.
die lesefunktion, die ich verwende, funktioniert, hab ein 'hallo' damit 
schonmal lesen können. der ursprüngliche inhalt vom lesearray war 
gefüllt mit zahlen und meine lesefunktion füllt das lesearray mit 
nullen, da auf den gelesenen block nicht, wie erwünscht 255 
reingeschrieben wurde.
lese und schreibe-funktion wird auch diesselbe addresse übergeben.

ist alles etwas mega kompliziert formuliert, aber vielen vielen dank für 
jeden tipp

von Brue W. (brue)


Lesenswert?

Ich wuerde raten, die Kartenresponse und das CRC Token auszuwerten, ggf. 
nach dem Kommando das Status register zu lesen. Dort sieht man nämlich 
dann wo das Problem liegt.

von fpga_thorben (Gast)


Lesenswert?

danke für den tipp, ich mach das mal ;-)

von fpga_thorben (Gast)


Lesenswert?

ich hätte noch eine frage. kann ich den crc auch einfach deaktivieren? 
oder muss der sein? in der initialisierungsfunktion habe ich so eine 
option z. b. nicht.

von MRS (Gast)


Lesenswert?

Ohne die Antwort auf deine Frage zu wissen, warum ließt du dir nicht 
einfach die Spezifikation durch, anstatt dich durch ein Forum zu fragen? 
Umständlicher gehts doch kaum...

https://members.sdcard.org/downloads/pls/simplified_specs/part1_410.pdf

von fpga_thorben (Gast)


Lesenswert?

ich hab die mir mehrmals angeschaut und gelesen, hab auch geschrieben, 
dass ich nichts dazu wirklich gefunden habe, ob man es deaktivieren kann 
und hab halt nochmal nachgefragt, ob dies auch so ist

von Brue W. (brue)


Lesenswert?

Nein kann man nicht. Nur im SPI mode kann man es optional deaktivieren.
Gruss

von MRS (Gast)


Lesenswert?

fpga_thorben schrieb:
> ich hab die mir mehrmals angeschaut und gelesen, hab auch geschrieben,
> dass ich nichts dazu wirklich gefunden habe, ob man es deaktivieren kann
> und hab halt nochmal nachgefragt, ob dies auch so ist

Ok, ich nehm alles zurück.

fpga_thorben schrieb:
> hab in der sd karten spec nur ein 'crc error status' für einen command
> gefunden, nicht fürs datenschreiben.

Habe das hier übersehen.

von fpga_thorben (Gast)


Lesenswert?

alles gut
ich schreibe, falls es was neues gibt ;-)

von fpga_thorben (Gast)


Lesenswert?

vllt noch eine frage, hat jemand es hinbekommen im 4 bit modus auf die 
karte zu schreiben und kann mir den code vllt senden?
ich habe bereits diesen verwendet, leider das gleiche ergebnis, konnte 
nicht auf die karte schreiben...


Beitrag "Sd-Card endlich im 4-Bit-Mode! -> Init  Read  Write"

von fpga_thorben (Gast)


Lesenswert?

initialisierung klappt, lesen auch. die karte hat fat32 format.

ich sende den cmd24 mit blockadresse, kriege eine antwort, dass alles 
okay ist.

dann wird die clock gesetzt, nullen für den start gesendet, bits 
rübergesendet, danach crc und am ende mit 1 der transfer beendet. es 
wird gewartet, bis die datenleitung 1 eine 1 ist und wird noch 8 mal die 
clock übertragen.

von fpga_thorben (Gast)


Lesenswert?

joooo, hab die fehler gefunden. alles richtig gemacht. bloß im 
vorgegebenem code war die 4 bit modus initialisierung der ausgangspins 
falsch und am ende wurde zu kurz auf das busy der sd karte gewartet ;-)

von fpga_thorben (Gast)


Lesenswert?

ich hätte noch eine frage, ich hab 3 sd karten evaluiert und ist voll 
lahm.

liegt es am prozessor? hab 50 mhz am start.

bevor ich schreibe, wie schnell es ist, wollte ich vorab fragen, ob der 
spi modus höhere raten schafft, weil man ja auf crc verzichtet?

von fpga_thorben (Gast)


Lesenswert?

also, im spec steht ja, dass 12 MB/s möglich sind. wenn ich es jetzt mit 
nem fpga mache, kriege ich die rate oder dauert auch die berechnung des 
crc's der sd karte ziemlich lange?


vielen dank für antworten

von grundschüler (Gast)


Lesenswert?

4bit-modus in software macht wohl nicht wirklich Sinn. Wenn, dann crc in 
hardware. Und dann mit ausgereiftem code  z.B. von Elm Chan - für alles 
andere ist das Leben zu kurz.

von fpga_thorben (Gast)


Lesenswert?

das heißt ich kann davon ausgehen, wenn ich es in vhdl z. b. realisiere 
und es läuft, dann hab ich deutlich höhere datenraten? brauch nämlich 10 
mbyte/s fürs lesen und 3 fürs lesen. software seitig hab ich nicht mal 
ein zehntel davon ;-).

von grundschüler (Gast)


Lesenswert?

fpga_thorben schrieb:
> 10 mbyte/s fürs lesen

das ist gewaltig. ich hatte im 1-bit-sdio-Modus 1,8 mbytes/sec:
Beitrag "Re: sd-card SDIO Initialisierung"

im 4-bit modus wären das dann ca. 6 mbyte/s.

von fpga_thorben (Gast)


Lesenswert?

Also, falls ich mich nicht irre, ist ja eig. der 4 bit Mode die 
schnellste Übertragung. die Karten haben ja eine mind. Datenrate, die 
sie schaffen. Im default modus sind 12mbytes/s ja, je nach kartentyp 
drin. Mir geht es nicht um mein System, dass die frequenzen nicht 
einhält, da mach ich mir eher keine sorgen. Ich bin mir nicht sicher, ob 
wegen des CRC's die Rate nicht erreicht werden kann, weil die SD Karte 
zu lange braucht, um den CRC zu berechnen. Ich hab 3 Karten getestet und 
alle haben eine unterschiedliche Datenrate, was mich stützig macht. Eig. 
müssten die alle gleich schnell sein. ich erreiche beim lesen bei einer 
um die 440 kbytes/s, bei einer anderen Karte nur 330. Das lässt mich 
vermuten, dass die Karte mega lahm ist.
Beim Schreiben erreiche bei einer 119 kbyte/s bei einer anderen nur 89.

Woran könnte das liegen?

Die Größte (8 GByte) ist die langsamere (Klasse 4)

und die Kleinste (512MByte) die schnellste.

Hätte eher gedacht dass die Größte schneller wäre als die kleinere, 
wegen Klasse 4. Und überhaupt, dass beide gleich schnell sind, weil die 
Karten halt nicht von der Geschwindigkeit her ausgelastet werden.

von grundschüler (Gast)


Lesenswert?

ich zitiere mich selbst:

Ausprobiert habe ich 3 8GB-sdKarten. Ergebnis für beide Modi:
Karte 1 ~600kbyte/sec
Karte 2 ~1200kbyte/sec
Karte 3 ~1900kbyte/sec

Meine Vermutung: Karte3 wird ohne besondere Initialisierung immer im
4bit-Modus betrieben, bei den beiden anderen Karten funktioniert die
Umstellung  nicht.

Beitrag "sdio problem mit 4bit-modus"

von Brue W. (brue)


Lesenswert?

fpga_thorben schrieb:
> Also, falls ich mich nicht irre, ist ja eig. der 4 bit Mode die
> schnellste Übertragung.
Ja, wobei es hierbei noch weitere Unterteilungen gibt.
Eine Übersicht gibt hier 
https://www.sdcard.org/developers/overview/bus_speed/index.html oder der 
Standard. Normal Speed (4 bit und  25 MHz) bietet bis zu 12.5MB/s (50 
MHz). Das etwas schnellere High Speed bis zu 25MB/s. Nebst diesen, gibts 
ausserdem noch die UHS Modis die noch höhere Geschwindigkeiten erlauben. 
Verschiedene Karten können verschiedene Modis unterstützen oder eben 
nicht. Der Host muss umschalten (Da gibts Kommandos dafür), falls er 
einen anderen Modus verwenden will.

Das ist die Bus-Datenrate wohlgemerkt. Das ist das Maximum was vom Bus 
her möglich ist. Die tatsächliche Geschwindigkeit ist dann von 
Kartentype zu Type unterscheidlich und auch davon abhängig, in welchem 
Zugriffmuster geschrieben/gelesen wird.

Die Frage wäre daher, wie du denn die Performance misst und bei welchem 
Zugriffsmuster.


> drin. Mir geht es nicht um mein System, dass die frequenzen nicht
> einhält, da mach ich mir eher keine sorgen. Ich bin mir nicht sicher, ob
> wegen des CRC's die Rate nicht erreicht werden kann, weil die SD Karte
> zu lange braucht, um den CRC zu berechnen. Ich hab 3 Karten getestet und

Die Karten haben einen dafür spezialisierten Controller verbaut, die die 
CRC in Hardware erledigen.

Gruss

von fpga_thorben (Gast)


Lesenswert?

Alles klar, danke für die Ínfos. Ich werd wohl wahrscheinlich es auf nem 
Altera Fpga den Shit implementieren und berichten, obs klappt bzw. wie 
schnell es dann geht ;-)

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

fpga_thorben schrieb:
> brauch nämlich 10
> mbyte/s fürs lesen und 3 fürs lesen.
Lies den Satz nochmal genau ;-) High-Performance und Software-Bitbanging 
passen irgendwie nicht zusammen. Ein FPGA ist aber auch nicht nötig. Mit 
einem STM32F7 und dessen Hardware-SDIO habe ich bis zu 15 MByte/Sec bei 
<1% CPU-Last geschafft. Dazu braucht es aber viel Puffer-RAM. Optimal 
dafür ist das STM32F746GDISCOVERY, das hat genau das was man braucht.

von fpga_thorben (Gast)


Lesenswert?

hey, hey.
Ich hab ein neues Problem. Hab multiple block read hinbekommen. lese 512 
byte blocks und beende es mit cmd12. das klappt soweit. jedoch will ich 
multiple block write ebenfalls hinkriegen. die block write funktion 
funktioniert wunderbar. Wenn ich aber mehrmals block write durchziehe 
und cmd12 sende, um das Schreiben zu beenden, dann geht der nächste 
befehl nicht und hab nen unexpected status.

Wenn ich den cmd25 sende, mehrere schreibe, cmd12 schicke, dann krieg 
ich ne unerwarteten zustand als antwort und lesen bzw. schreiben geht 
nicht mehr. wenn ich die karte neu initialisiere, kann ich jedoch den 
multiple block, den ich geschrieben auch lesen. bloß muss halt vorher 
neu initialisieren. ich find aus der spec nicht wirklich raus, was ich 
falsch mache.


für hilfe wäre ich sehr erfreut :-).

von Jim M. (turboj)


Lesenswert?

fpga_thorben schrieb:
> . Wenn ich aber mehrmals block write durchziehe
> und cmd12 sende, um das Schreiben zu beenden, dann geht der nächste
> befehl nicht und hab nen unexpected status.

Das mit dem Busy im Programming State (DAT0 low) hattest Du gesehen? In 
dem Zustand nimmt er nur ganz wenige Befehle an.

von fpga_thorben (Gast)


Lesenswert?

meinst du nach einen block write? dort berprüfe ich es. ebenso in cmd12. 
dort warte ich nach der antwort auf busy.

von fpga_thorben (Gast)


Lesenswert?

jo, war mein fehler, an der falschen stelle nach dem busy gefragt, 
klappt bei mir nachdem ich die antwort bekommen habe. hab da nen blöden 
fehler gemacht ;-).

von Mana (Gast)


Lesenswert?

Hallo fpga_thorben,

ich habe den crc-Datencheck genauso gemacht. Es funktioniert aber bei 
mir noch nicht.
Hier folgt ein Teil meiner Schreibfunktion:

SD_DAT_OUT;  // set DAT pins to send data to SD card

// start bits
SD_CLK_LOW;
SD_DAT_WRITE(0x00);
SD_CLK_HIGH;

// write data (512 bytes = 1 block)
for(i = 0; i < nDataLen; i++)    // nDataLen = 512
{
    Data8 = szDataWrite[i];      // was ich in der SD-Karte schreiben 
möchte
    #ifdef SD_4BIT_MODE
        for(j = 0; j < 2; j++)
  {
      SD_CLK_LOW;
      SD_DAT_WRITE((Data8 >> 4) & 0x0F);
      SD_CLK_HIGH;
      Data8 <<= 4;
  }
    #endif
}

// Crc-Datencheck
#ifdef SD_4BIT_MODE
    for(j = 0; j < 16; j++)
    {
        SD_CLK_LOW;
        Crc16Aux = DataCrc16 >> 15;

        if (Crc16Aux  == 0x01)
      SD_DAT_WRITE(0x0F);
        else
      SD_DAT_WRITE(0x00);
        SD_CLK_HIGH;
        DataCrc16 <<= 1;
    }
#endif

// stop bits (value '1')
SD_CLK_LOW;
#ifdef SD_4BIT_MODE
    SD_DAT_WRITE(0x0F);
#endif
SD_CLK_HIGH;

//===== check busy bits (data0 only).
SD_DAT_IN;    // set DAT pins to receive data from SD card

for(i = 0; i < 32 && !bWriteSuccess; i++) // Glaub sollte nur 12 bits 
sein
{
    SD_CLK_LOW;
    SD_CLK_HIGH;    // CRC response output is always two clocks after 
the
                    // end of data

    if ((SD_TEST_DAT & 0x01) == 0x01) // (DAT0==LOW: busy indicate
        bWriteSuccess = TRUE;
}

    if (!bWriteSuccess)
      bSuccess = FALSE;

Das ist die Sequenz: S (Start Bit), content (512 bytes), CRC (16 bit für 
jede der vier Leitungen DAT0-3), E (End Bit)

Es wird in der SD-Karte nicht geschrieben und ich weiß nicht warum?
Hast Du bzw. hat Jemand eine Idee?
fpga_thorben, ist es möglich Deine Schreibfunktion zu zeigen?

von Mana (Gast)


Lesenswert?

Brue W. schrieb:
> Danach kommt von der Karte ein crc
> status token dass einem mitteilt ob die Daten richtig empfangen wurden
> oder nicht. Falls sie das wurden, kann die Karte danach busy werden um
> schlieslich die Daten zu programmieren.

Hallo Brue W.,

so wie ich es verstanden habe, sollte Z Z S Status E S L*L E Z, also 12 
Bits von der Karte empfangen werden, wobei

Z: High impedance state (-> = 1)
S: Start Bit (= 0)
Status: '101'(transmission error), '010'(non-erroneous transmission)
E: End Bit (=1)
L: Signal is low (logical ‘0’)
*: Repeater?

Ich bekomme aber ein anderes crc status token:
1 1 0  1 0 1   1 0 1 1 1 ... 1
Z Z S  Status  E S L*L E Z

Nach dem 10. Bit bekomme ich immer 1.

Ich dachte, dass ich das crc falsch berechne, aber ich bekomme mit 255 
den gleichen Wert, also 60841, wie im Beispiel von fpga_thorben.

Kann es an dem Takt liegen, da ich den Takt setze/schicke gleichzeitig 
wenn ich die Daten zu der SD-Karte schicke?

for(i = 0; i < nDataLen; i++)
{
    Data8 = szDataWrite[i];
    #ifdef SD_4BIT_MODE
    for(j = 0; j < 2; j++)
    {
        SD_CLK_LOW;
        SD_DAT_WRITE((Data8 >> 4) & 0x0F);
        SD_CLK_HIGH;
        Data8 <<= 4;
    }
}

Ich weiß nicht, was ich falsch mache. Ich habe schon einen Teil meines 
Codes hier hochgeladen. Ich weiß echt nicht, was ich ändern soll.

Hat jemand eine Idee?

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.