SD-Karten am Attiny

Hier können Sie ihre eigenen Projekte vorstellen
Antworten
Heinrichs
Beiträge: 101
Registriert: Do 21. Okt 2010, 16:31

SD-Karten am Attiny

Beitrag von Heinrichs » Sa 25. Aug 2012, 19:05

Um keine falschen Hoffnungen zu erwecken: Große Sprünge kann man mit SD-Karten am Attiny2313 nicht machen. Noch nicht einmal ein einfaches Datei-System wie FAT16 lässt sich implementieren. Dazu sind sowohl der Programmspeicher als auch der SRAM-Speicher des Attiny einfach zu knapp bemessen. Wer aber z. B. größere Mengen an Messdaten speichern möchte, der braucht nicht unbedingt ein solches Dateisystem und findet hier deswegen eine relativ einfache und vor allem preiswerte Möglichkeit.

Drei Dinge gilt es zu meistern:

1. Die SD-Karte an den Mikrocontroller anschließen
2. Die SD-Karten-Kommunikation kennenlernen
3. Entsprechende Programme erstellen
sd_karten_adapter.jpg
SD-Karten-Adapter
sd_karten_adapter.jpg (66.48 KiB) 8042 mal betrachtet

Anschließen der SD-Karte

Natürlich kann man einfach ein paar Kabel an die Kontakte der SD-Karte anlöten. Aber das ist aus zwei Gründen nicht zu empfehlen: Zum Einen kann man sie dann nicht mehr in einen SD-Karten-Slot stecken, zum anderen sollten die SD-Karten-Pins auch nicht direkt mit den Ports des Mikrocontrollers verbunden werden. Die SD-Karten arbeiten in der Regel mit 2,7-3,6 V, unser Attiny hingegen mit 5,0 V. Glücklicherweise kann man für 1 - 2 Euro Adapterplatinen erstehen, die nicht nur die Kontakte herstellt, sondern auch die Pegel anpasst (vgl. Abb. 1).

Diese Platine schließen wir gemäß folgender Tabelle an unsere Attiny-Platine an:
anschlusstabelle.jpg
Anschlusstabelle
anschlusstabelle.jpg (23 KiB) 8042 mal betrachtet

SD-Karten-Kommunikation

Gut lesbare Einführungen zu diesem Thema findet man unter

http://www.uni-koblenz.de/~physik/informatik/ECC/sd.pdf
und
http://alumni.cs.ucr.edu/~amitra/sdcard ... _foust.pdf .

Deswegen möchte ich mich hier auf das Notwendigste beschränken. Insbesondere setze ich hier voraus, dass der Leser Grundkenntnisse vom SPI-Protokoll besitzt. Die Kommunikation mit einer SD-Karte kann auf zweierlei Weisen erfolgen, in einem speziellen SD-Protokoll oder in dem SPI-Protokoll. Beide Protokolle ähneln sich. Das SPI-Protokoll bietet etwas weniger Möglichkeiten als das SD-Protokoll, es ist aber einfacher und manchem vielleicht auch schon von anderen Geräten her bekannt. Wir werden hier nur mit dem SPI-Protokoll arbeiten.

Jede SD-Karte besitzt einen Flash-Speicher und einen Controller mitsamt einer Reihe von Registern, die u. A. den Zustand der Karte beschreiben. So gibt es z. B. ein Register zur Identifizierung der SD-Karte; mit dem Inhalt dieses so genannten CID-Registers lässt sich eine SD-Karte eindeutig identifizieren. Dieses Register lässt sich im Gegensatz zu manchen anderen natürlich nicht überschreiben. Auf den Flashspeicher kann man nicht direkt zugreifen. Dies erfolgt nur über den Controller und ein Pufferregister. Dieses Pufferregister ist i. A. deutlich rascher als der Flashspeicher.

Um dem SD-Karten-Controller mitzuteilen, welche Aktion man von ihm erwartet, benutzt man sogenannte Commands. Ein solches Command besteht aus 6 Bytes. Das erste Byte gibt die Befehlsnummer an. Genauer: Das erste Byte ist die Befehlsnummer + $40; CMD17 hat z. B. als erstes Byte $40 + 17 = $40 + $11 = $51. Die nächsten 4 Bytes bestehen aus Parametern; das letzte Byte ist ein Kontrollbyte. Dieses Kontrollbyte stellt eine Prüfsumme (CRC) aus den ersten 5 Bytes dar; es wird im SPI-Modus aber normalerweise ignoriert. Nur an einer einzigen Stelle (beim CMD0, s. u.) muss es tatsächlich korrekt angegeben werden. Allerdings ist immer darauf zu achten, dass das CRC-Byte immer ungerade sein muss; häufig benutzt man hier deswegen die Werte $01 oder $FF. Die SD-Karte quittiert das Kommando mit einem oder mehreren Antwortbytes und führt die entsprechenden Aktionen aus. In den für uns relevanten Fällen besteht die Antwort immer nur aus einem einzigen Byte; dieses Byte muss sich der Master bei der SD-Karte abholen. An dem Antwortbyte lässt sich erkennen, ob Fehler beim Kommando aufgetreten sind:

Bit 7: immer 0
Bit 6: Parameter-Fehler
Bit 5: Adress-Fehler
Bit 4: Löschsequenz-Fehler
Bit 3: CRC-Fehler
Bit 2: Unzulässiges Kommando
Bit 1: Lösch-Reset
Bit 0: im Leerlauf

Es kann sein, dass die SD-Karte beim Abholen durch den Master noch keine Antwort bereit gestellt hat. In diesem Fall ist die Leitung MISO bei allen Takten auf High, und damit erhält der Master das Byte $FF. Insbesondere hat das Bit 7 nicht den Wert 0; dies zeigt, dass es sich bei dem abgeholten Byte nicht um ein Antwort-Byte handeln kann. In diesem Fall muss der Abholvorgang wiederholt werden.

Ein Kommando muss immer dadurch eingeleitet werden, dass die nSEL-Leitung auf Low gezogen wird. Deswegen setzen wir vor dem Senden der Kommando-Bytes nSEL auf 1, warten einen kurzen Augenblick (durch Senden eines Dummy-Bytes) und setzen dann nSEL auf 0.


Folgende Aktionen sollen hier vorgestellt werden:

• Initialisieren der SD-Karte
• Lesen eines Blocks
• Schreiben eines Blocks
• Lesen des CID-Registers (stellvertretend für alle anderen Register)


Zur Initialisierung der SD-Karte muss nach dem Einschalten zunächst mindestens 1 ms gewartet werden; die SD-Karte stellt gewissermaßen eine Kapazität dar und so braucht es etwas Zeit, bis die Betriebsspannung erreicht ist. Danach muss nSEL auf 1 gesetzt und mindestens 74 Clock-Signale mit MOSI auf High gesendet werden. Erst danach kann man das erste Kommando senden, nämlich CMD0. Wir senden dieses Kommando mit nSEL = 0, dadurch wird die SD-Karte in den SPI-Modus versetzt. In diesem Zustand verbleibt sie dann bis zum Ausschalten.

Das Kommando CMD0 hat keine Parameter; die Prüfsumme CRC ist in diesem Fall $95, und die Bytefolge dieses Kommandos ist damit $40:$00:$00:$00:$00:$95. Dies ist (im SPI-Modus!) der einzige Fall, bei dem die SD-Karte die Prüfsumme tatsächlich kontrolliert; in allen anderen Fällen wird sie ignoriert und kann deswegen willkürlich gesetzt werden. Ist das Kommando erfolgreich ausgeführt worden, antwortet die Karte mit dem Wert 1. Das bedeutet, sie ist in den Leerlauf (idle-mode) versetzt (vgl. die obigen Fehlercodes). Es kann sein, dass dieses Kommando mehrfach gesendet werden muss, bis es erfolgreich ausgeführt werden konnte.

Jetzt muss die Karte vom Leerlauf in den Betriebsmodus versetzt werden. Dazu benutzt man das Reset-Kommando CMD1. Parameter gibt es wieder keine und als CRC-Byte wählen wir die ungerade Zahl 1. Das vollständige Kommando ist dann: $41:$00:$00:$00:$00:$01. Wurde das Kommando erfolgreich ausgeführt, dann erhalten wir als Antwort den Wert 0 (“Kein Leerlauf”). Auch hier ist es durchaus möglich, dass mehrere Versuche erforderlich sind.


Kommen wir nun zum Lesen eines Datenblocks. Der Flashspeicher der SD-Karte ist in Blöcke unterteilt; ein solcher Block besteht in der Regel aus 512 Bytes. Näheres kann man z. B. dem Manual der Firma SanDisk entnehmen. Mit dem Block-Lesen-Kommando CMD17 kann man einen solchen Block auslesen. Als Parameter wird die Startadresse des zu lesenden Blocks angegeben. Dabei wird allerdings nicht die Nummer des Blocks benutzt, sondern die Adresse des ersten Bytes dieses Blocks. Wollen wir z. B. den Block 3 auslesen, hat das erste Byte dieses Blocks die Adresse 3*512 = 6 * 256 = 6 * $100 = $600. Der vollständige Befehl lautet dann: $51:$00:$00:$06:$00:$01. Ist kein Problem aufgetreten, antwortet die SD-Karte mit dem Wert 0. Das bedeutet aber noch nicht, dass die Daten dieses Blocks schon abgeholt werden können; die Karte muss diese Daten nämlich - wie oben schon angedeutet - erst in einen Puffer schieben. Ist dieser Vorgang abgeschlossen, sendet die Karte das Token (Startzeichen) $FE. Auf dieses Byte muss der Mikrocontroller warten, bis er die 512 Bytes der Reihe nach auslesen kann. Danach sendet die SD-Karte noch 2 Prüfbytes; diese müssen vom Mikrocontroller abgeholt werden, auch wenn wir sie nicht nutzen.

Das Schreiben eines Blocks geschieht auf ähnliche Weise wie das Lesen. Das zugehörige Kommando ist CMD24. Will man z. B. Daten in den Block 3 schreiben, lautet das Kommando $58:$00:$00:$06:$00:$01. Wurde das Kommando akzeptiert, erhält man die Antwort 0. Danach sollte man eine kurze Zeit verstreichen lassen (80 Clocks reichen nach meinen Erfahrungen aus.). Jetzt muss der Mikrocontroller das Token $FE senden, und danach können die Datenbytes nacheinander an die SD-Karte gesendet werden. Zum Abschluss müssen noch zwei Prüfbytes an die SD-Karte übertragen werden; diese können willkürlich gewählt werden, da sie von der SD-Karte nicht ausgewertet werden. Ist die Übertragung insgesamt erfolgreich verlaufen, sendet die Karte ein Byte von der Art XXX00101. Dabei sind die X-Bits ohne Bedeutung. Danach ist die Karte in der Regel noch damit beschäftigt, die empfangenen Daten aus dem Puffer in den Flash zu transportieren. In dieser Zeit ist die MISO-Leitung auf Low. Erst wenn der Schreibvorgang vollständig abgeschlossen ist, wird die MISO-Leitung wieder auf High gezogen. Soll der Mikrocontroller das Ende des Schreibvorgangs abwarten, muss er demnach so lange Bytes von der SD-Karte holen, bis das empfangene Byte den Inhalt $FF hat.


Das CID-Register besteht aus 16 Bytes. Um es auszulesen, benutzt man das Kommando CMD10. Parameter gibt es keine. Die Bytefolge lautet demnach $4A:$00:$00:$00:$00:$FF. Ansonsten ist die Vorgehensweise mit der beim Lesen eines Blockes identisch.


Wichtiger Hinweis: Wenn Sie die SD-Karte später noch anderweitig nutzen wollen (z. B. am PC oder im Fotoapparat), dann sollten Sie die ersten Blöcke nicht überschreiben. Hier stehen nämlich wichtige SD-Karten-spezifische Daten. Es könnte sein, dass PC oder Fotoapparat ohne diese Daten die Karte nicht mehr akzeptieren. Meine Experimente habe ich mit einer alten Canon 16-MB-Karte durchgeführt. Bei ihr begann der Datenbereich anscheinend bei Block 64.


Programme

Die Beispielprogramme sind in BASCOM geschrieben. Sie gehen teilweise an die Grenze des zur Verfügung stehenden Speicherplatzes. Das liegt aber zum Teil daran, dass zur Vereinfachung des Programms machtvolle (und damit speicherintensive) BASCOM-Befehle benutzt wurden. So füllt der Input-Befehl für die Eingabe der Blocknummer nahezu 10% des Programmspeichers. Die für den Betrieb der SD-Karte wesentlichen Programmteile benötigen wesentlich weniger Speicherplatz. Die kommentierten Beispielprogramme findet man in der Anlage.
Dateianhänge
sdsource.zip
Source-Code
(5.21 KiB) 1148-mal heruntergeladen

Antworten