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.
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 ;)
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.
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.
@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.
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.
@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?
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 :)
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.
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
@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.
> 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
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?
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.
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! :-(
>> 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.
> 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
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.
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.
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?
> 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.