Kommunikationsprobleme mit SPI / SD-Karte

Ich arbeite mit einem PIC18F67K22 und sehe einige bizarre Dinge im SPI-Datenstrom. Ich versuche, mit FatFs und einer benutzerdefinierten diskio.c-Datei mit einer FAT32-Partition zu interagieren. Ich kann die FAT32-Partition erkennen, aber beim Versuch, eine Datei zu erstellen, gibt die disk_read-Operation plötzlich seltsame Fehler aus.

Ich habe einen Screenshot der Logik zwischen dem PIC18 und der SD-Karte angehängt, um die ungewöhnlichen Daten zu zeigen.

Geben Sie hier die Bildbeschreibung ein

Im Screenshot sehen Sie, dass ich CMD17 (READ_SINGLE_BLOCK) zusammen mit einer 4-Byte-Adresse von 0x00007D10 und einer CRC7-Prüfsumme für diesen Befehl sende.

Die Befehlsantwort, die ich erhalte, ist 0xC1, gefolgt von 0x3F, was keinen Sinn ergibt. Laut dem Abschnitt How to Use MMC/SDC auf der FatFs-Website sollte das höchstwertige Bit der Befehlsantwort immer eine 0 sein, aber bei 0xC1 ist das höchstwertige Bit auf 1 gesetzt. Warum kommt außerdem 0x3F danach? Das sollte 0xFF sein.

Und selbst wenn ich annehmen würde, dass hier eine Bitverschiebung vorliegt und der tatsächliche Wert 0xC13F >> 6 (0x04) sein sollte, wäre das ein illegaler Befehl. Was ist an CMD17 mit dieser Adresse illegal? Ist die Datenadresse von 0x00007D10 ungültig? Die Partition sollte sich über das gesamte Medium erstrecken, mit Ausnahme des MBR und des Boot-Datensatzes.

Bearbeiten:

Hier sind die während der Initialisierung zurückgegebenen Sektoren mit einigen Anmerkungen zu den Daten:

Bearbeiten 2:

Ich habe festgestellt, dass dies nur passiert, wenn ich f_mount lange vor f_open aufrufe. Ich mache beim Einlegen der SD-Karte einen f_mount, um zu überprüfen, ob die Karte eine richtige FAT16/FAT32-Partition ist, und rufe dann nur f_open auf, wenn der Benutzer beginnt, Daten aufzuzeichnen. Wenn ich f_mount und f_open in schneller Folge aufrufe (oder f_mount mit verzögertem Mounten aufrufe), funktioniert der Aufruf einwandfrei und der Befehl gibt 0x00 und dann 512 Byte Daten zurück.

Sie sollten wahrscheinlich die gesamte Init-Sequenz bis zu diesem Punkt posten. Nennen Sie uns Ihre clk-Rate. Sehen Sie sich die Blockgröße an und prüfen Sie, ob Sie mit dieser Adresse eine Blockgrenze überschreiten.
Meine Taktrate beträgt die ganze Zeit 2,66 MHz. Ich habe die Dumps des MBR und des Boot-Records von Partition 1 hinzugefügt. Beim Kommentieren sind mir einige ziemlich bizarre Dinge aufgefallen. Der Boot-Datensatz von Partition 1 besagt, dass es 0 Sektoren pro FAT gibt, was seltsam erscheint. Und die Datenträgerbezeichnung ist alles nicht druckbare ASCII. Lese ich im falschen Bereich? Ich denke, meine Endianness ist an manchen Stellen seltsam geworden. Windows erkennt die SD-Karte problemlos, daher denke ich, dass die Karte richtig formatiert ist.
Gibt es vor der Bildschirmaufnahme einen Übergang von Chip Select High zu Chip Select Low? Vielleicht gibt die Karte zum Zeitpunkt der Erfassung noch Festplattendaten aus?

Antworten (1)

Ein Jahr ist vergangen, seit die Frage gestellt wurde, aber ich habe mich entschieden, sie zu ergänzen, weil ich ähnliche Probleme beim Einbetten des SD-Kartentreibers in FPGA hatte. Ich stimme den Kommentatoren zu Ihrer Frage zu, dass Sie Informationen darüber geben müssen, was vor dem fehlgeschlagenen SPI-Zyklus passiert ist und was danach passiert.

Obwohl es eine SD-Spezifikation für die SD-Karten gibt, ist sie im Allgemeinen etwas verwirrt und hat mich dazu gebracht, nicht eine Stunde damit zu verbringen, zu verstehen, was an meinem Design falsch ist.

So lass uns anfangen...

  • Initialisierung: Es ist Voraussetzung, dass freie Taktzyklen mit deaktiviertem CS vorhanden sind, damit sich die Karte selbst initialisiert und versteht, dass es einen Host gibt. Es wird auch eine Vorstellung davon bekommen, welche Art von SPI verwendet wird.
  • Start des Befehlszyklus: Sie benötigen freie Taktzyklen, bevor Sie CS Low aktivieren, um den Befehl zu starten, und idealerweise mehrere Taktzyklen, nachdem Sie CS Low aktivieren und beginnen, den Befehl auf die MOSI-Leitung zu legen. Mehrere bedeutet hier n*8. Diese Ersatzzyklen sind erforderlich, um sicherzustellen, dass sich die Karte vom vorherigen E/A-Zyklus erholt, wenn ein Problem aufgetreten ist (z. B. Ihre Anwendung hat nicht alle Daten/Status übertragen, und die Karte erwartet immer noch, dass der Host diese Daten oder diesen Status liest/sendet). Ein sparsames Takten mit CS High wird die Karte davon überzeugen, dass der vorherige Vorgang abgebrochen werden sollte.

Als ich diese beiden oben richtig gemacht habe, habe ich keine ungültigen Antwortcodes mehr von der SD-Karte erhalten. Es gibt einige andere Besonderheiten bei der Handhabung von SD-Karten über SPI, aber sie sollten bei Bedarf behandelt werden, da der Befehlszyklus selbst, dann die Antwort- und die Datenphase in der Spezifikation relativ gut erklärt sind und Sie wahrscheinlich keine Probleme bei der Implementierung haben werden.