mikrocontroller.net

Forum: Compiler & IDEs microSD-Karte lesen


Autor: Julian M. (jvm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe eine 2GB-microSD-Karte von Sandisk hier, und moechte auf die 
Daten zugreifen. Zum Testen meiner Hardware dachte ich, verwende ich mal 
das Beispielprogramm der avrlib von Pascal Stang unter examples/mmc. Nur 
Taktfrequenz richtig eingetragen und Programm auf einen ATMEGA8 
geflashed. Das Initialisieren ging nicht. Ich habe dann Dokumentation 
gelesen und die Initialisierungsfunktion ueberarbeitet, jetzt schliesst 
es immer erfolgreich mit einem erfolgreichem Return-Code (0) ab. (Bis 
alles erfolgreich durchlaeuft sind meistens drei Schleifendurchlaeufe 
erforderlich.)
Nach dem Initialisieren wuerde ich gerne Lesen ;) Beim Lesen des Sektors 
0 bekomme ich Daten zurueck, die nichts mit den auf der Karte 
enthaltenen Daten zu tun haben, aber eindeutig fuer die Karte sind. 
(Eine zweite, baugleiche Karte liefert reproduzierbar andere Werte, 
auch, nachdem beide Karten per "dd" synchronisiert wurden.)
Frage: Woran kann es liegen, dass ich Bloedsinn lese, wie sollte ich 
vorgehen um das Problem genauer zu analysieren, wieso sind die gelesenen 
Daten eindeutig fuer die Karte, aber unabhaengig von den auf der Karte 
gespeicherten Daten?

Zweite Frage:
In der avrlib steht
r1 = mmcCommand(MMC_READ_SINGLE_BLOCK, sector<<9);
im Beispiel der elm-Bibliothek hingegen
if ((send_cmd(CMD17, sector) == 0)  /* READ_SINGLE_BLOCK */
Letzteres wirkt plausibler. Was hat sich Pascal bei seiner Variante 
gedacht?

Vielen Dank fuer Tipps
Julian

Hier noch meine veraenderte Initialisierungsfunktion: (einzige Aenderung 
gegenueber der avrlib von Pascal Stang)
u08 mmcReset(void)

{

  u08 i;

  u08 retry;

  u08 r1=0;



  retry = 0;

  do

  {

    // send dummy bytes with CS high before accessing

    for(i=0;i<10;i++) spiTransferByte(0xFF);

    // resetting card, go to SPI mode

    r1 = mmcSendCommand(MMC_GO_IDLE_STATE, 0);

    #ifdef MMC_DEBUG

    rprintf("MMC_GO_IDLE_STATE: R1=0x%x\r\n", r1);

    #endif

    // do retry counter

    retry++;

    if(retry>10) return -1;

  } while(r1 != 0x01);



  for (retry = 0; retry < 10; retry++) {

    r1 = mmcSendCommand(CMD55, 0);

    #ifdef MMC_DEBUG

    rprintf("CMD55: R1=0x%x\r\n", r1);

    #endif

        if (r1 != 5) continue;



    r1 = spiTransferByte(0xFF);

    #ifdef MMC_DEBUG

    rprintf("DUMMY: R1=0x%x\r\n", r1);

    #endif

        if (r1 != 255) continue;



    r1 = mmcSendCommand(MMC_SEND_OP_COND, 0);

    #ifdef MMC_DEBUG

    rprintf("MMC_SEND_OP_COND: R1=0x%x\r\n", r1);

    #endif

        if (r1 != 0) continue;



    r1 = spiTransferByte(0xFF);

    #ifdef MMC_DEBUG

    rprintf("DUMMY: R1=0x%x\r\n", r1);

    #endif

        if (r1 != 255) continue;



    r1 = mmcSendCommand(MMC_CRC_ON_OFF, 0);

    #ifdef MMC_DEBUG

    rprintf("MMC_CRC_ON_OFF: R1=0x%x\r\n", r1);

    #endif

        if (r1 != 0) continue;



    r1 = spiTransferByte(0xFF);

    #ifdef MMC_DEBUG

    rprintf("DUMMY: R1=0x%x\r\n", r1);

    #endif

        if (r1 != 255) continue;



      // set block length to 512 bytes

      r1 = mmcSendCommand(MMC_SET_BLOCKLEN, 512);

      #ifdef MMC_DEBUG

      rprintf("MMC_SET_BLOCKLEN: R1=0x%x\r\n", r1);

      #endif

        if (r1 == 0) return 0;

  }



    return -1;

}

edit: Verwendeter Schaltplan: 
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1206874649/8 mit 
Pinbelegung fuer die SD-Karte von 
http://www.planetmobile.it/jumpjack/adattatore/pin... und das 
ganze natuerlich an die SPI-Ports vom ATMEGA8.

Autor: Olaf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gegenfrage: Woher weisst du was im Sektor0 stehen muss?
Liess die Karte mal unter linux mit dd aus.
Wenn du es bisher unter Windows gemacht hast dann kann dein Problem 
daran liegen das dich Windows wie gewoehnlich bescheisst und dir nicht 
den Bootsektor angezeigt hat sondern den ersten Sektor deiner Partition.

Olaf

Autor: Julian M. (jvm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hatte dd doch bereits erwaehnt? Ich habe eine Karte FAT16 
formatiert, zwei Dateien ins root-Directory, die Rohdaten komplett 
gelesen, auf die zweite Karte per dd draufgeschrieben, und die Rohdaten 
im Hexeditor analysiert. Wie erwartet ein "MSDOS" und "FAT16" im ersten 
Sektor, viele Nullen, und irgendwann meine beiden Dateien.
Das Demoprogramm aus der avrlib gibt die Daten gleich nett formatiert 
per UART aus. Eine Zeichenkette in den von dem Demoprogramm ausgegebenen 
Daten kann der Hexeditor in den vorher kopierten Rohdaten aber nicht 
finden, ausserdem liest das Demoprogramm jedesmal das gleiche, auch wenn 
ich die Karte mit anderen Daten beschreibe. Das spricht dafuer, dass das 
Demoprogramm Bloedsinn liest.

Autor: Julian M. (jvm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aehm...obwohl ich deine Antwort gerade als Bloedsinn abtat, war sie die 
Loesung: Wer immer dd if=/dev/sde1 of=... zum Kartenlesen verwendet, 
verpasst natuerlich den ersten Sektor. Kaum liest man wirklich die ganze 
Karte, hat man die gleichen Daten, wie das Demoprogramm sie auch liest.

Ich entschuldige mich vielmals, und bedanke mich!
(An alle Leute die Probleme mit MicroSD-Initialisierung haben: die 
avrlib mit obiger Reset-Funktion laeuft bei meiner 2GB-Sandisk-Karte, 
die Originalversion hingegen nicht. Der Beispiel-Code der elm-Bibliothek 
initialisierte bei mir auch nicht richtig.)

Autor: Olaf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nochmal einen kleinen Tip dazu.

Wenn man Daten auf so einer Karte ablegen will dann gibt es 
normalerweise
zwei Moeglichkeiten.

1. Man schreibt sie raw einfach irgendwo hin, muss aber dann
   dann im Betriebssystem ebenfalls raw lesen.

2. Man unterstuetzt halt das FAT DAteisystem und hat dabei den
   entsprechenden aufwand.

Eine gute Loesung dazwischen ist es wenn man auf seiner leeren Karte
eine Datei anlegt die garantiert groesser ist als man fuer seine
Daten braucht. Es ist aber wichtig das die Karte vorher leer ist
damit die Datei nicht fragmentiert ist.
In den ersten Bytes seiner Datei legt man dann eine komplizierte
Bytefolge als Magicnumber. Der Controller sucht dann beim einlegen
nach dieser Nummer und weiss dann ab wo die Datei am Stueck auf der
Karte liegt. Danach kann er seine Daten einfach hinter die Nummer 
schreiben.
Damit umgeht man das Problem das eine Datei auf verschieden grossen 
Speicherkarten auf verschiedenen Sektoren beginnen wird, kann aber 
andererseits die Daten auf seinem Betriebssystem ganz einfach lesen. 
Letzeres sogar mit einem Texteditor wenn der Controller sie als ASCII 
ablegt.

Olaf

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.