Hallo ihr Experten!
mir macht zur Zeit mein µC meines Datenloggers ein wenig
Schwierigkeiten!
Verwendet wird ein AT90CAN128. Peripherie ist eine RTC und ein
SD-Card-Slot.
Der Datenlogger loggt Daten mit und schreibt diese alle 960 ms auf eine
SD / MMC - Karte. Der verwendete Bus ist der SPI-Bus. Dieser wird zuerst
mit ca. 125 kHz initialisiert, also eig. so wie das OK sein sollte (
<400 kHz ). Nach einer kurzen Delay-Time und dem Senden von mind. 74
Clocks und den entsprechenden Commands an die Karte ist diese
initialisiert.
Nun wird der SPI Bus auf 2 MHz eingestellt, da die verwendeten
Pegelwandler nicht mit Frequenzen >3 MHz arbeiten können. Zusätzlich
wird ein FAT16 Dateisystem initialisiert.
Komisch ist nun, dass sich nach unbestimmter Zeit, z.B. mal nach 2 1/2
Stunden, 4 Stunden, 6 3/4 Stunden das Programm bzw. die Software einfach
aufhängt und nicht mehr weiterarbeitet! Im Debugmodus konnte
herausgefunden werden, dass wohl der Schreibzyklus für ein Byte
(sd_write_byte()-Funktion) zu lange dauert. Aber warum geht das die
ersten 2-3, manchmal auch 5-6 Stunden gut? Ich meine, so werden
Langzeitmessungen eig. unmöglich!!
Hat jemand ne Idee, an was dies legen könnte? Pegelwandler (MAX3371)
vllt. ?!
Viele Grüße
S.
Vermutlich wird das Wearleveling der SD Karte aktiv. Einige SD Karten
benötigten beim Schreiben ab und zu mal etliche 100ms bis >500ms für
einen Sektor.
Du musst halt einen ausreichend großen Puffer im RAM vorsehen, in den
alle Daten passen die in dieser Zeit ankommen.
Das Problem waere eher etwas fuer die Kategorie : Wie debuge ich ein
Programm. Das beinhaltet Software und Hardware, die sich etwas anders
verhaelt als urspruenglich angenommen.
Wenn man natuerlich nach jedem sektor, um den das file laenger wird das
Direktory updatet, so hat man verloren. Ich wueerd mal ein file der
maximalen leange allozieren, und nachher nur noch auf die betroffenen
Sektoren zugreifen. Und nur ganze sektoren neu schreiben, keine
teilweisen sektoren.
Hallo.
Erstmal vielen Dank für eure Antworten!
@ Benedikt:
Ist es möglich, dieses Wearleveling der SD-Karte irgendwie zu umgehen
(z.B. durch schnelleren Clock ?!) bzw. auszuschalten (womöglich durch
ein Command?!) ? Würde dann aber die Karte nicht einfach die Daten
verwerfen und neu starten ? Oder hängt sie sich komplett auf ?
Ansonsten ist das mit dem Puffer eine gute Idee.
@pfft.:
Was meinst du mit "Wie debugge ich ein Programm" ? Das Programm lief
über eine JTAG-Schnittstelle online mit. Als der Fehler auftrat wurde
PAUSE geklickt und der gelbe Pointer des AVR-Studios stand bei oben
genannter Funktion (sd_write_byte())! Ich habe vorher bereits vermutet,
dass es an einer der Schreibfunktionen liegen muss bzw. an irgendeiner
Funktion, welche irgendwann den SPI-Bus zu lange belegt. Da klingt doch
das von Benedikt genannte Wearleveling ganz plausibel.
Habt ihr sonst noch irgendwelche Ideen?
Bin über jede Antwort dankbar!
Viele Grüße
S.
> Im Debugmodus konnte herausgefunden werden, dass wohl der> Schreibzyklus für ein Byte (sd_write_byte()-Funktion) zu lange dauert.
Zu lang für was? Wo steht denn, wie lange der Zyklus dauern darf?
Du kannst niemals davon ausgehen, dass eine C-Funktion in der Zeit
lim->0 abgearbeitet wird.
Ich habe an etliche Hersteller von Compactflashs mal die Frage gestellt,
wie lange die Versorgungsspannung nach dem letzten Schreibbefehl (und
abschliessendem fclose() ) noch stabil anliegen muß, dass die Daten
sicher auf dem CF gespeichert werden. Eigentlich eine einfache Frage,
aber die Antworten reichen von "keine Reaktion", über "typisch 300ms"
bis "in der Regel maximal 600ms".
Im Endeffekt habe ich dann den Dosenöffner genommen und automatisiert
über jeweils eine Woche direkt an den Steuerleitungen des Flashspeichers
im CF gemessen. Heraus kam, dass die von den Herstellern vorher
abgelieferten Zahlenwerte eigentlich nur irgendwelche Hausnummern
waren... :-o
>Als der Fehler auftrat wurde>PAUSE geklickt und der gelbe Pointer des AVR-Studios stand bei oben>genannter Funktion (sd_write_byte())! Ich habe vorher bereits vermutet,>dass es an einer der Schreibfunktionen liegen muss bzw. an irgendeiner>Funktion, welche irgendwann den SPI-Bus zu lange belegt. Da klingt doch>das von Benedikt genannte Wearleveling ganz plausibel.
Nicht unbedingt. Wenn der SS Pin nicht als Ausgang
definiert ist, oder als Eingang mit Pullup, kann es zu
solchen SPI Hängern kommen. Grund dafür ist das schon
ein kurzes Low auf SS reicht um den Master in den
Slave Modus zu schalten. Wenn der SS Pin floatet
reicht es schon mit der Hand in die Nähe der Schaltung
zu kommen.
Gast schrieb:
> Ist es möglich, dieses Wearleveling der SD-Karte irgendwie zu umgehen> (z.B. durch schnelleren Clock ?!) bzw. auszuschalten (womöglich durch> ein Command?!) ?
Nein.
> Würde dann aber die Karte nicht einfach die Daten> verwerfen und neu starten ? Oder hängt sie sich komplett auf ?
Fragst du ab ob die Karte bereit ist, oder sendest du einfach drauf los?
Wenn das ganze für immer an der Stelle hängen bleibt, dann ist das nicht
das Wear Leveling, sondern sonst ein Problem in der Software oder der
Hardware.
Datentragerzugriffsprozeduren duerfen natuerlich nicht blockierend sein.
Sie muessen einen Schreib/Lesefehler abfangen koennen, und neu
aufsetzten. Falls eine Operation nach Reties nicht funktioniert, so muss
das Programm weiter laufen koennen.
Hallo,
nochmal vielen Dank für die Antworten. Hab mir jetzt mal die SW nochmals
durchgeschaut und versuche euch mal das Problem bzw. die SW etwas
genauer zu erläutern.
Die Daten werden alle in einer Textdatei (*.txt) formatiert gespeichert.
Es wird die Uhrzeit (empfangen über TWI-Schnittstelle) geschrieben und
dann die relevanten Werte zu diesem Zeitpunkt (je 67 Stück). Und das,
wie erwähnt, alle 960ms. Soweit so gut.
In der main()-Funktion wird zuerst abgefragt ob die *.txt - Datei
vorhanden ist. Wenn nicht, wird sie angelegt. Auch noch simpel.
Danach wird eine Funktion gerufen, welche vom CAN-Bus die Daten
empfängt. Dabei wird zuerst die Uhrzeit (vom TWI empfangen und)
geschrieben und dann die vom CAN-Bus empfangenen Daten. Dabei wird
geprüft, ob im aktuellen Sektor noch Platz ist, wenn nicht, wird der
nächste geladen. Gleichermaßen wird mit dem Cluster verfahren. Wenn
alles OK ist, dann wird das Byte auf die Karte geschrieben.
Zuvor wird natürlich ein Sektor an die Karte geschrieben, in welchen
dann die Daten geschrieben werden. Dabei wird CMD24 gesendet, der Befehl
zum Senden von 512 Bytes bzw. 1 Sektor. Danach wird ein Clock gesendet
und das StartByte bzw. das sog. Datatoken (0xFE). Danach wird der Sektor
bzw. die 512 Bytes geschrieben und das / die CRC-Byte/s, welche aber im
SPI-Mode ja sowieso ignoriert werden. Es wird nun gewartet, bis die
Karte wieder bereit ist und der SPI wird wieder disabled.
Erst dann werden die eigentlichen Daten geschrieben. Im Prinzip wurde
sich größtenteils an die Sourcecodes von U.Radig und R.Riegel
orientiert. Also dürfte das eigentlich soweit passen!
Ich frag mich langsam echt, was da los ist?!
Mit freundlichen Grüßen
S.
Du meinst also, dass ein PullUp-Widerstand auf der SS Leitung fehlt ? Da
muss ich mich nachher mal erkundigen, bin aber grade in ein anderes
Projekt vertieft. Sobald's was Neues gibt, meld' ich mich.
Trotzdem schon mal vielen Dank für eure Tipps!
Was könnte man, vorausgesetzt der PullUp wäre dran, noch dagegen machen
?
MfG
Hallo,
nun ja, es werden vier bidirektionale Pegelwandler (MAX3371) verwendet,
welche alle einen internen PullUp enthalten. Diese hängen je an SS,
MISO, MOSI und SCK (Clock) der SPI. Beim Senden eines Commands an die
Karte wird zuerst über SS disabled, dann werden mittels
sd_write_byte(0xFF) 8 Clock Impulse (0xFF) gesendet wobei anschließend
die Karte wieder über SS enabled wird. Ist diese Zeit bzw. sind die
Clocks vielleicht zu kurz ? Danach wird das Command gesendet und auf
eine Antwort der Karte gewartet mittels:
// Wartet auf eine gültige Antwort von der MMC/SD-Karte
while (tmp == 0xff)
{
tmp = sd_read_byte(); // sd_read_byte() gibt nach Erfolg 0
if (Timeout++ > 300) break; zurück
}
sd_write_byte(0xFF); // Sendet 8 Clock Impulse
return(tmp)
Wären unidireketionale Pegelwandler vielleicht besser?
MfG
S.
Ist SS bei dir ein Ausgang, oder Eingang?
Wenn SS an CS der SD Karte geht, dann müsste dies doch eigentlich ein
Ausgang sein. Von daher dürfte es eigentlich keine Probleme geben. Prüf
das mal.
Der Port wurde als Ausgang definiert:
DDRB |= (1<<SPI_MOSI) ... Es wird auch nicht mehr umgestellt.
Das dürfte eigentlich keine Probleme machen!?
MfG
S.
>Der Port wurde als Ausgang definiert:>>DDRB |= (1<<SPI_MOSI) ... Es wird auch nicht mehr umgestellt.
Da sehe ich nur MOSI.
Entweder irgendeine Ausgabe auf DDRB schaltet den Pin
auf Eingang, oder SPCR wird von irgendwas so zermatscht
daß das SPI Modul deaktiviert wird.
Lass das ganze mal laufen und schau mit dem Debugger nach ob SS wirklich
auf Ausgang ist, wenn das ganze sich aufhängt.
Ansonsten bleibt der µC natürlich auch hängen wenn kein Wert gesendet
wurde, und trotzdem gewartet wird, bis die Übertragung fertig ist. Dazu
müsstest du deine Software man genau anschauen ob das sein kann.
Komplett ist die Init wie folgt:
DDRB &=~(1<<SPI_MISO); //Setzt den Pin MMC_DI als Eingang
DDRB |= (1<<SPI_Clock); //Setzt den Pin MMC_Clock als Ausgang
DDRB |= (1<<SPI_MOSI); //Setzt den Pin MMC_DO als Ausgang
DDRB |= (1<<SPI_SS); //Setzt den Pin SPI_SS als Ausgang
DDRB |= (1<<SD_VCC); //Setzt den PIN SD_VCC als Ausgang
MISO,usw. als defines der Portnummern. Also nix weltbewegendes!
werd morgen das mal ausprobiern. danke
gruß