Speicherkarten-Daten auslesen zu langsam

Gast #1010431
Lesenswert?

Hi,

ich hab ein (kleines) Problem bei der Ansteuerung meiner SD Karte. Das 
Auslesen von Daten aus einer Datei usw. klappt wunderbar, aber es ist 
mir zu langsam.

Ich steuere die Karte via SPI an, mein CPU Takt beträgt 16 MHz...
Bei einem Prescaler von 8 (2 MHz) funktionierts noch, beim Prescaler 4 
(4 MHz) nicht mehr, woran kann das liegen?
Ich dachte die SD Karten kommen mit einem Takt von 20 MHz klar (laut 
Datenblatt)??

Danke schonmal im Voraus.
Gast #1010506
Lesenswert?

im Datenblatt vom ATmega128 steht nur die Output Spannung

Output Low Voltage
(Ports A,B,C,D, E, F, G) :     0,7 V

Output High Voltage
(Ports A,B,C,D, E, F, G) :     4.2 V


Aber beim TWI Steht bei Input High: 0,7*Vcc das wären 3,5 V und 3,3 V 
wären dann schlecht...
die Frage ist dann nur, warum es bei 2 MHz überhaupt funktioniert?


Gibt es ne schnelle Möglichkeit den Pegel anzuheben ohne noch so ein IC 
zu verwenden und ohne die Spannung des µC zu verändern?
#1010512
Lesenswert?

Die Ausgangsspannungen interessieren hier nicht, die Eingangsspannungen 
sind wichtig:
Input High Voltage except XTAL1 and RESET pins: 0.6*VCC, also 3V bei 5V.
Bei 3,3V Spannung sind das nur 0,3V mehr, was eben zusammen mit dem 4,7k 
Widerstand eine zusätzliche Verzögerung bewirkt.
Versuch es mal ohne den Widerstand.

Die beste Lösung wäre ein HCT245 oder irgendwas in der Art, denn dieser 
hat Schaltschwellen bei etwa 0,8V bzw. 2V. Am Ausgang liefert er 0V/5V.
Gast #1010523
Lesenswert?

naja aber ich kann den LVC245 nicht durch den HCT ersetzen sondern 
brauch wieder ne extra schaltung...mist, hätt ich mir vorher überlegen 
sollen..


Ohne den Widerstand gehts garnicht, nicht mal bei nem Takt von 125 KHz, 
mit dagegen einwandfrei, wieder bis 2 MHz...
Angehängte Dateien:
Gast #1010532
Lesenswert?

So sieht mein SPI Init aus:

SPI_DIR |= (1 << MOSI) | (1 << SCK) | (1 << SS);
SPI_PORT |= (1 << MOSI) | (1 << SCK) | (1 << SS);

SPI_DIR &= ~(1 << MISO);

SPCR = (1 << MSTR) | (1 << SPE);

SPCR |= (1 << SPR0) | (1 << SPR1);                                SPSR 
|= (1<<SPI2X);


kann kein pullup mehr dazwischen klemmen ohne die schaltung zu 
zerstören, ist schon fertig geätzt :(
Gast #1010576
Lesenswert?

Ja es lag daran und an den LVC, keine ahnung warum ich die Outputdaten 
von der SD Karte noch dadurch jagen wollte....

ich habe jetzt eine Rate von 512 Bytes in 7 µs
das sind doch knapp 70 MB/s, kann das stimmen?
Gast #1010593
Lesenswert?

meine messung habe ich wie folgt vorgenommen:

Sd Karte initialisiert.

Datei geladen.

Timer wie folgt initialisiert:

TCCR1A=0x00;
TCCR1B=0x01;         //Prescaler 1 -> 16 MHz
TCNT1=0x10000 - 16;  //---> 1 MHz -> jede µs
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

Timer gestartet (mit TIMSK=0x04)
-> Timerinterrupt jede µs->zähler wird erhöht, TCNT1 wird zurückgesetzt

Ein Block (512 Bytes) angefordert

Timer gestoppt (mit TIMSK=0x04)

Ausgabe der 512 Bytes (sind korrekt)
und ausgabe des Zählers (7 µs)


wo ist der Fehler?? Kann ja nur beim timer sein
#1010598
Lesenswert?

Hirbel wrote:

> Timer gestartet (mit TIMSK=0x04)
> -> Timerinterrupt jede µs->zähler wird erhöht, TCNT1 wird zurückgesetzt

Alle 16 Takte ein Interrupt? Vergiss es!

> Ausgabe der 512 Bytes (sind korrekt)
> und ausgabe des Zählers (7 µs)

Mit ein wenig Nachdenken hättest du eigentlich selbst drauf kommen 
können, dass dies nicht sein kann:
SPI hat 8MHz, also 8MBit/s. 512Byte sind 4kBit. Wenn du für 8bit 1µs 
brauchst, dann kannst du in 7µs maximal 56Bit übertragen, aber nie 
4kBit.
Gast #1010602
Lesenswert?

na ich habe ja glaube geschrieben das es nicht sein kann...
habe den fehler gefunden...beim zurücksetzen von TCNT1 stand ein alter 
wert drin....
so komme ich auf 7 ms und grad mal 71 KByte/s
...langsam....
(Firma: TravelRec.) Persönliche Seite #1010628
Lesenswert?

Ahaaa. Rein theoretisch sind 512Bytes gut einer halben ms drin, wenn 
Dein Controller nichts anderes mehr machen muß. Also macht Dein 
Controller die anderen 6 1/2 ms noch irgendwelchen anderen Kram. 
Vielleicht kannst Du da noch optimieren. Oder aber der Controller wartet 
auf ein Busy von der Karte. Da könnte dann nur noch das Kommando 
"MultiBlockRead" etwas helfen. Ich erreiche bei meinen Karten bei 16Mhz 
SPI (XMega@32Mhz) etwas über 400kByte/s beim Single Block lesen. Du 
kannst natürlich auch Deinen Controller übertakten. 25Mhz machen die 
meisten ATMEGAs problemlos mit.
#1010758
Lesenswert?

Travel Rec. wrote:
> Ahaaa. Rein theoretisch sind 512Bytes gut einer halben ms drin, wenn
> Dein Controller nichts anderes mehr machen muß. Also macht Dein
> Controller die anderen 6 1/2 ms noch irgendwelchen anderen Kram.

Ja, nämlich das hier:

> TCCR1B=0x01;         //Prescaler 1 -> 16 MHz
> TCNT1=0x10000 - 16;  //---> 1 MHz -> jede µs
> ICR1H=0x00;
> ICR1L=0x00;
> OCR1AH=0x00;
> OCR1AL=0x00;
> OCR1BH=0x00;
> OCR1BL=0x00;
>
> Timer gestartet (mit TIMSK=0x04)
> -> Timerinterrupt jede µs->zähler wird erhöht, TCNT1 wird zurückgesetzt

Wenn der AVR jede µs einen Interrupt ausführt, dann geht da fast die 
ganze Rechenleistung drauf.
So eine Zeitmessung macht man anders:
Den Timer auf 0 setzen und starten. Im Overflow Interrupt eine weitere 
8/16bit Variable erhöhen. Nun hast du zusammen mit dem 16bit Timer einen 
24/32bit Zähler mit 62,5ns Auflösung und einem Messbereich bis 1s/256s.
Wenn du fertig bist, stoppst du den Timer mit TCCR1B=0;
Nun kannst du das Timer Register und die Variable auslesen und ausgeben.

Ich wette dann bist du mindestens doppelt so schnell.
Beim Lesen sind die SD Karten in der Regel sehr schnell, so dass fast 
nur der SPI Takt + Overhead zwischen den Bytes eine Rolle spielen. Ich 
schreibe sogar mit rund 100kByte/s mit einem mega8 @10MHz...
#1012397
Lesenswert?

Irgendwie kommt mir das etwas komisch vor:
Wenn du vorher wirklich den Timer alle 1µs einen Interrupt hast 
ausführen lassen, dann wäre diese zu (4 Takte Interrupteintritt, 4 Takte 
um Register zu retten, und das ganze nochmal beim Verlassen, also 16 
Takte insgesamt, dann nochmal 10 Takte um eine 16bit Variable zu 
erhöhen, macht also mindestens mal 26 Takte. Deine erste Messung war 
vermutlich also komplett falsch.

Da deine zweite Messung fast dasselbe Ergebnis liefert, und bei der 
ersten Messung der µC eigentlich die ganze Zeit im Interrupt verbringen 
müsste, kann da irgendwas nicht passen.
Gast #1012416
Lesenswert?

meine interrupt routine sieht so aus:

_timer1_overflow:
  ST   -Y,R30
  ST   -Y,R31
  IN   R30,SREG
  ST   -Y,R30
  MOVW R30,R6
  ADIW R30,1
  MOVW R6,R30
  LD   R30,Y+
  OUT  SREG,R30
  LD   R31,Y+
  LD   R30,Y+
  RETI

Sind genau 22 Takte (Codevision compiler)...
also ich weiß nich wo der fehler liegt :(
Gast #1012797
Lesenswert?

welchen rest denn?
die ganzen sd-karten routinen für die ansteuerung?
neee das ist zu viel...

wenn bei beiden Messungen 7 ms rauskommt, warum sollte es da einen 
Fehler geben, ich versteh das nich so ganz...
#1012803
Lesenswert?

Hirbel wrote:
> meine interrupt routine sieht so aus:
>
> _timer1_overflow:
>   ST   -Y,R30
>   ST   -Y,R31
>   IN   R30,SREG
>   ST   -Y,R30
>   MOVW R30,R6
>   ADIW R30,1
>   MOVW R6,R30
>   LD   R30,Y+
>   OUT  SREG,R30
>   LD   R31,Y+
>   LD   R30,Y+
>   RETI
>
> Sind genau 22 Takte (Codevision compiler)...
> also ich weiß nich wo der fehler liegt :(

Wenn der Code (bzw. etwas ähnliches das du vorher hattest) 22 Takte 
braucht, er aber alle 16 Takte ausgeführt wurde, dann kann da was nicht 
passen.

Wenn du es nun anders machst, und immer noch das selbe rauskommt, dann 
kann da was nicht passen.
Gast #1012809
Lesenswert?

na das mit den 22 Takten bekomme ich ja nun nicht kleiner hin...

ich könnte den timer langsamer laufen lassen, so das ich garkeine 
Intterupt routine brauche, sonder TCNT1 ausreicht, also nie der overflow 
erreicht wird...
aber ich wette da kommt dann das gleich raus
(Firma: TravelRec.) Persönliche Seite #1012810
Lesenswert?

>wenn bei beiden Messungen 7 ms rauskommt, warum sollte es da einen
>Fehler geben, ich versteh das nich so ganz...

Weil 7ms das 7-fache davon ist, was der Controller eigentlich an Zeit 
braucht, um die Daten auf der Karte abzulegen. Wenn Kartenschreibzeit 
und andere Routinen im zeitlichen Verhältnis von etwa 1:1 vorliegen 
würden, würde ich ja gar nichts sagen. Aber so vertrödelst Du einfach 
irgendwo Zeit, die Du vielleicht andernorts brauchen könntest.
#1012817
Lesenswert?

Hirbel wrote:
> na das mit den 22 Takten bekomme ich ja nun nicht kleiner hin...

Darum gehts ja auch nicht.

Ich machs mal an einem einfachen Beispiel:
Du liest ein Buch mit 512 Seiten.
Du liest nur 1h pro Tag, da du die restliche Zeit mit etwas anderem 
zubringst.
Jetzt liest du das Buch nochmal, diesmal liest du aber 23h pro Tag. 
Trotzdem brauchst du 512 Tage.
Wenn du beidesmal genausoschnell gelesen hast, dann muss irgendwo ein 
Fehler sein, denn dann kann das nicht stimmen.

Wenn du alle 1µs, also alle 16 Takte den Timer Interrupt ausführst, 
dieser aber 22 Takte braucht, dann
- passt die Zeitmessung nicht
- ist der Prozessor zu 22/23, also 96% mit dem Timer Interrupt 
beschäftigt

Wenn dein Code hierbei genausolange braucht, als wenn er nur z.B. 1% im 
Timerinterrupt verbringt, also 99% der Rechenleistung zum Lesen hat, 
dann kann irgendwas nicht stimmen.

Zeig also mein deinen ganzen Code!
Gast #1012820
Lesenswert?

sooo der timer lief jetzt mit 2MHz.
TCNT1 hatte den Wert 13423, das sind wieder 6,7115 ms
die Messung ist also korrekt oder nich?

es stimmt schon, das ich zeit vertrödele, in dem ich auf die SD karte 
warte (busy wait) aber das geht doch nun mal nich anders ??
Gast #1012832
Lesenswert?

ja die ist schon entwas älter und sieht sehr mitgenommen aus...

anbei mal die sd.c, fat32.c (nicht alles auf meinem mist gewachsen) und 
die main.c (steht auch anderes zeug drin -> nicht beachten).

also ein wenig zeit geht auch drauf, weil er zu einer bestimmten stelle 
in einer datei springt...aber das ist nicht viel (hab ich schonmal 
auskommentiert)
Angehängte Dateien:
Gast #1012841
Lesenswert?

hab mal ne neuere Karte genommen, da sinds jetzt immerhin "nur" noch
6,6555 ms ;)

kann es evtl. sein, das es an der takt oder datenleitung liegt?
hab dafür nur ein 0,2 mm kupferlackdraht genommen und alle leitungen 
zusammengedreht....???
#1012860
Lesenswert?

Achso, du liest nicht nur die Daten, sondern suchst erst noch den Sektor 
aus der Cluster Chain usw.
Das erklärt einiges.

Les mal z.B. 16x 512Bytes und mess dabei mal die Zeit.
Dann sollten deutlich >100kByte/s rauskommen.

Meine Erfahrung war bisher, das die Datenrate bei bis zu rund der Hälte 
des der SPI Frequenz liegt, also bei dir bei rund 4MBit/s=500kByte/s.
Hängt natürlich auch von der Geschwindigkeit des Prozessors usw. ab.

In der sd.c könntest du bei der Lesefunktion noch
*(buffer + i) = card_sendbyte(0xFF);
durch
*buffer++ = card_sendbyte(0xFF);
ersetzen, das sollte der Compiler deutlich besser optimieren können.

Und die card_sendbyte Funktion selbst, die solltest du als inline 
deklarieren, denn der Sprung + Rücksprung dauert fast so lange wie das 
Lesen selbst.
Und die Timeoutabfrage in der Funktion ist eigentlich auch unnötigt. 
Nach 16 Takte ist der SPI Transfer fertig, wenn nicht dann ist irgendwo 
was gewaltig schief gelaufen, da hilft dann auch keine Abfrage mehr.

Ansonsten sieht der Code gut aus. Wenn du mehrere Blöcke liest, und den 
Code wie angegeben etwas optimiert, dann sollten definitiv >100kByte/s 
rauskommen.
Gast #1012882
Lesenswert?

okay, ich hab das mit dem buffer abgeändert und 10 mal die gleichen 512 
bytes gelesen (ohne Seek, also vom anfang der datei)...

und man glaubt es kaum, aber ich komme auf 7,067 ms für 512 bytes :(
Gast #1012907
Lesenswert?

ach naja ich lass das jetzt erstmal so, alles in asm umzuschreiben, da 
hab ich jetzt keine lust zu 70KByte sind ja 560 kbit/s das dürfte für 
mp3 anwendungen ausreichen?

Kannst mir aber auch deine routinen zur verfügen stellen, wenn du willst 
:)


Vielen Dank aber erstmal für doe Hilfe.
#1012911
Lesenswert?

Hirbel wrote:
> ach naja ich lass das jetzt erstmal so, alles in asm umzuschreiben, da
> hab ich jetzt keine lust zu

Musst du auch nicht.
Mit dem Code von ELM-Chan erreiche ich >200kByte/s (alles in C).
http://elm-chan.org/fsw/ff/00index_e.html

> 70KByte sind ja 560 kbit/s das dürfte für mp3 anwendungen ausreichen?

Ja, sollten eigentlich. Mehr als 320kBit/s gibt es bei den normalen mp3s 
ja nicht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren