Forum: Mikrocontroller und Digitale Elektronik sd-Karte Blockgröße < 512 Byte


von Andi S. (laserandi)


Lesenswert?

Hallo Leute,
mir ist es gelungen eine 1 GB (Platinum bzw Kingston)
sd-Karte in 512 Byte Blöcken "RAW" zu lesen und zu
schreiben. Für meine Anwendung dauert das lesen aber
zu lange. Deshalb habe ich versucht mit CMD 16 die
Blockgröße auf 16 Byte zu ändern. Der µC kann aber immer
nur die Blöcke lesen, die genau ein Vielfaches von
512 sind. Bei allen anderen Blöcken entstehen immer
Lesefehler.

Im Forum steht, dass Stefan Seegel für einen MP3 Player
die Blockgröße ändern konnte. Leider habe ich aber den
Quellcode und den Kartentyp nicht finden können.

Falls es sonst jemandem gelungen ist, die Blockgröße
zu ändern, wäre ich für Tips sehr dankbar.

von Gast (Gast)


Lesenswert?

Nur mal so als Idee in den Raum gestellt....

Wenn die Karte nur über den AVR angesteuert werden soll, könnte man 
einfach die ungenutzten Bytes eines Sektors als NULL definieren und mit 
Dummy-Werten beschreiben. Dann müsste man nur soviel RAM aufwenden, wie 
ein virtueller Sektor groß ist, der Rest wird im Loop mit einer 
Konstanten beschrieben/gelesen. Wenn man 128 Byte große Sektoren 
benutzt, geht ein viertel der Kapazität verloren. Dafür hätte man 
theoretisch z.B. schon an einem Controller mit 128 Byte RAM satte 256MB 
Speicher bei einer 1GB-SD-Karte. Dürfte Preis-Leistungstechnisch und 
auch von der Handhabung her schwer zu schlagen sein ;)

von Andi S. (laserandi)


Lesenswert?

Danke für die Idee.
Das ist zwar nicht die eleganteste Lösung, da ich max. 16 Byte lesen 
will, aber immerhin wäre es eine Möglichkeit.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Du kannst doch auch nen kleinen Buffer anlegen der die Zeit welche die 
Karte zum lesen braucht überbrückt, sobald die 512byte gelesen sind 
kannst du die ja nacheinader auslesen und mußt nur wieder soviel puffern 
das das lesen des nächsten Blocks dann shcon beendet ist.

von Andi S. (laserandi)


Lesenswert?

@Läubi
Das verstehe ich nicht so ganz. Während ich die 512 Byte - Blöcke von
der Karte lese ist der µC doch blockiert. Das ist ja genau das Problem.
Partielles auslesen in kleinen Blöcken funktioniert halt nicht.

Vielleicht habe ich mich oben etwas unverständlich ausgedrückt.
Ich möchte z.B. 8000 Byte von der sd-Karte lesen und möglichst schnell 
verarbeiten.
Das funktioniert auch prima, bis der Puffer von 512 Byte abgearbeitet 
ist.
Dann muss ja der nächste Block von der Karte gelesen werden. Dadurch 
entsteht eine Pause, in der der µC blockiert ist und keine 
Datenverarbeitung stattfinden kann.
Eine Lösung wäre, immer nur sehr kleine Blöcke zu lesen, sodass auch nur 
kleine Pausen entstehen. Hier gibt es aber das Problem, dass viele 
sd-Karten eine feste Blockgröße von 512 Byte haben (was scheinbar auch 
bei meiner der Fall ist), wodurch sich immer nur kleine Blöcke, die 
genau ein Vielfaches von 512 Byte sind, lesen lassen.
Man könnte nun, wie bereits oben vorgeschlagen, die restlichen Bytes 
eines Blocks einfach ignorieren, da auf einer 1GB Karte sowieso genug 
Platz ist.

Diesen Lösungsansatz werde ich mal testen oder zur Not vielleicht auf 
einen anderen Speicher (FRAM o.ä.) zurückgreifen.

von Antwortengeber (Gast)


Lesenswert?

Hallo,


ich würde die Karte über den Interrupt lesen (512 Byte) und intern im uC 
auf 16 Byte runter gehen und diese kleinen Blöcke verarbeiten. Das läuft 
aber alles auf einen Datenstream hinaus, der dann die maximal 
performance bringt.

Der Interrupt füllt die Buffer und dein Core verarbeitet die Daten. Die 
eigentliche Denkarbeit steckt dann nur in der Datenflusskontrolle, aber 
das sollte kein Problem sein.


Grüße.

von Andi S. (laserandi)


Lesenswert?

@Antwortgeber
Ich stehe immer noch auf dem Schlauch.
Durch Interruptprogrammierung geht das Auslesen der 512 Byte Blöcke auch 
nicht schneller und die Datenverarbeitung wird trotzdem unterbrochen 
(Interrupt halt), oder wie soll ich das verstehen?

von Joe (Gast)


Lesenswert?

Mit dem Xmega würds gehen, hat nen DMA welcher die 512Byte schön 
rüberschaufelt während man mit dem Core die eigentliche Arbeit erledigt 
:)

von Antwortgeber (Gast)


Lesenswert?

Du kannst zwischen den Interrupts die Datenverarbeitung erledigen, wenn 
genug Zeit da ist. Wenn das auslesen von 512 Bytes plus 
Datenverarbeitung schon zu lange dauert dann benutzt du womöglich die 
falsche CPU. Mit 16 Byte Brocken muss es nicht besser werden, da du dort 
noch den Overhead hast.

von Hagen R. (hagen)


Lesenswert?

Normalerweise sollte es mit gößeren Blöcken immer besser als schlechter 
werden vom Timing her. Dein Problem ist das Verständnis was 
Double-Buffering heist. Statt einen 512 Bytes Buffer benutzt du zwei 
solcher Buffer. Während der eine Buffer im Hintergrund per ISR gefüllt 
wird kannst du den anderen auswerten und weiterverarbeiten. Diese 
Weiterverarbeitung wird 512 mal kurzeitig durch die SPI ISR unterbrochen 
aber das sind nur par Takte.

Desweiteren steht auch noch der Weg des schnelleren asynchronen Einlesen 
und Verarbeitens der Daten in Relation zur synchronen Ausgabe der Daten. 
Also angenommen es soll ein 44Khz Sound ausgegeben werden der von SD 
Karte stammt. Der Ausgabebuffer wird mit 44Khz synchron ausgegeben, 
dauert bei 8Bit Samples  12ms. Die SD Karte wird aber mit 8Mhz 
angesteuert, somit rund 512µs zum Füllen eines Buffers. Man könnte hier 
nun mit 3 Buffern arbeiten. Der eine um die Daten der SD karte zu 
speichern, der andere um die Daten zu bearbeiten und der dritte um die 
Daten per 44Khz an DAC auszugeben. Jeder dieser 3 Buffer wird 
unterschiedlich schnell gefüllt, verändert und ausgegeben. Der erste 
Buffer wird am schnellsten gefüllt, der zweite bischen langsammer 
bearbeitet und der dritte am langsammsten wieder mit 44Khz ausgegeben. 
Sobald dieser fertig ist kommt es zum einzigst kritischen Moment, denn 
nun müssen die Buffer-Zeiger vertauscht werden. Somit entsteht ein 
Ringbuffer und ohne Verzögerungen oder Klicks können die Daten gelesen, 
verarbeitet und ausgegeben werden.

Gruß Hagen

von Andi S. (laserandi)


Lesenswert?

@Hagen
Aha. Ich denke, jetzt habe ich es verstanden. Die zweite Möglichkeit 
("asynchron Einlesen") hört sich für mich als newbie erstmal kompliziert 
an aber Möglichkeit 1 werde ich mal testen.
Danke an Hagen für die ausführliche Antwort.

@Antwortgeber
Der µC läuft mit 14,7456 MHz.
Die reine Datenverarbeitung für 10-Byte Blöcke dauert 70 µs (14,3 kHz).
Das Auslesen eines 512-Byte Blocks von der sd-Karte dauert 35 ms
(29 Hz). Mein Ziel ist eine kontinuierliche Datenverarbeitung von max.
1 ms (1 kHz) pro 10-Byte Block ohne die Pausen von 35 ms für das
Auslesen der Karte.
Das sollte per SPI-Interrupt machbar sein glaube ich.

von Peter (Gast)


Lesenswert?

> mir ist es gelungen eine 1 GB (Platinum bzw Kingston)
> sd-Karte in 512 Byte Blöcken "RAW" zu lesen und zu
> schreiben.
nimm am besten andere karten, sandisk z.b.
die kingston-dinger sind manchmal recht zickig im spi-modus.
ich habe eine hier, die gar nicht will, mit allen anderen gehts

von Zwirbeljupp (Gast)


Lesenswert?

Ist es eigentlich möglich, das Lesen eines Blocks nach z.B. 32 Bytes 
kurzzeitig zu unterbrechen, also die Karte zwar angewählt zu lassen (CS 
low), jedoch keine weiteren Clock zu senden und nach einer Pause von 10 
oder 100 ms das Lesen fortzusetzen?
Führt dies zu einem Timeout beim SD-Karten Controller?

von MG (Gast)


Lesenswert?

im sd-Card mode sollte das gehen. mit spi hab ich noch keine 
angesteuert.
Die karte bezieht ihren takt vom interface. also vom SPI oder SD-Card 
interface.

auserdem solltest du nicht vergessen, das ggf nach 512 byte eine neue 
addressierung eines sektors notwendig werden kann. je nach dem ob ein 
Dateisystem verwendet werden soll oder nicht.

von Drehgeber (Gast)


Lesenswert?

Gibt es eigentlich irgendwo eine gute Doku, wo beschrieben ist, wie man 
SD-Karten im SD-Card Modus (also mit 4 Datenleitungen) anspricht?
Und was sind das eigentlich immer für Kommandos, von denen alle reden? 
so CMD0 und so. Ich hab die noch nirgends finden können! :-(

von Peter (Gast)


Lesenswert?

>> mir ist es gelungen eine 1 GB (Platinum bzw Kingston)
>> sd-Karte in 512 Byte Blöcken "RAW" zu lesen und zu
>> schreiben.
> nimm am besten andere karten, sandisk z.b.
> die kingston-dinger sind manchmal recht zickig im spi-modus.
> ich habe eine hier, die gar nicht will, mit allen anderen gehts
jetz muss ich mir mal selber antworten: wenn man ein kommando an die 
karte schickt, darf man bei kingston den unbenutzten CRC nicht auf 0 
setzen, sondern er muss 0xFF. alle anderen karten akzeptieren beides, 
also 00 und ff. somit gehen bei mir jetzt auch die dämlichen 
kingston-karten.

gibt es hier eigentlich ein SD-card FAQ? ich finde das müsste da rein.

von Peter (Gast)


Lesenswert?

> Und was sind das eigentlich immer für Kommandos, von denen alle reden?
> so CMD0 und so.
hier ist eine kleine liste:
http://www.samsung.com/global/business/semiconductor/products/flash/downloads/applicationnote/MMC_HOST_Algorithm_Guide.pdf
kapitel 3

von Termite (Gast)


Lesenswert?

jep es gibt eine beschreibung bei http://www.sdcard.org "Simplified 
Specification" da sollte was software angeht so zimlich alles drinn 
sein. Die meisten timings und HW spezifischen sachen fehlen aber.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Zwirbeljupp wrote:
> Ist es eigentlich möglich, das Lesen eines Blocks nach z.B. 32 Bytes
> kurzzeitig zu unterbrechen, also die Karte zwar angewählt zu lassen (CS
> low), jedoch keine weiteren Clock zu senden und nach einer Pause von 10
> oder 100 ms das Lesen fortzusetzen?
> Führt dies zu einem Timeout beim SD-Karten Controller?

Genau das meinte ich: Du sagst der Karte sie soll einen Block lesen. 
Dann machst du erstmal was anderes (z.B. Datanverarbeiten) schaust ob 
die Daten bereit zum lesen sind und liest solange Daten bis die Karte 
wieder ne "denkpause" braucht. In der Zeit kannst du dann die gelesensen 
Daten verarbeiten so wie hagen beschrieben hat.

Das ist wie eine Kommunikation per UART:
- Du kannst in einer schleife Warten bis die UART bereit zum 
sende/empfangen ist --> Du bist blokiert und kannst nix anderes machen.
ODER:
- Du nuzt Interupts (der elegante Weg) und der Prozessor sagt dir dann 
wenn er bereit ist
- Du schaust in regelmäßigen Abständen nach ob das senden möglich ist 
(zyklisches pollen)

In beiden Fällen hast du dazwischen Zeit was anderes zu machen. Dafür 
mußt du natürlich ggf deine Kommunikationsroutinen anpassen.

von Drehgeber (Gast)


Lesenswert?

Schön, danke erstmal für den Link zu Samsung.
Jetzt weiss ich wenigstens mal, was CMD0 und so weiter ist. Aber: Was 
muss man machen, um einen CMD0 auszuführen? Sendet man da über SPI 
wirklich einen String "CMD0" oder was? Oder gibts da, ähnlich wie bei 
Festplatten, so einen Code? z.B. 0x12 für CMD0, 0x34 für CMD1 und so? 
Oder wie?

Und wo könnte man etwas über das 4Draht-Interface finden?

von Peter (Gast)


Lesenswert?

> Jetzt weiss ich wenigstens mal, was CMD0 und so weiter ist. Aber: Was
> muss man machen, um einen CMD0 auszuführen? Sendet man da über SPI
> wirklich einen String "CMD0" oder was?
hier ist es erklärt, unter 'Command and Response'
http://elm-chan.org/docs/mmc/mmc_e.html

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.