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.
Ist eine EEPROM Write funktion blockierend ? Wozu waer das denn gut ? Das waer aber ganz schlecht. In die Tonne mit dem Dreck.
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.
Und wo bleibt die Software jetzt genau hängen? Beim Warten auf die SD Karte oder sonstwo?
Sie bleibt in der Funktion sd_write_byte() hängen. Und zwar an folgender Stelle: while(!(SPSR & (1<<SPIF))); // Wartet bis Byte gesendet wurde MfG
>Sie bleibt in der Funktion sd_write_byte() hängen. Und zwar an folgender >Stelle: > >while(!(SPSR & (1<<SPIF))); // Wartet bis Byte gesendet wurde Das kann nur das hier sein: Beitrag "Re: µC eines Datenloggers hängt sich nach unbestimmter Zeit auf !"
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
>Was könnte man, vorausgesetzt der PullUp wäre dran, noch dagegen machen >? Den Pin auf Ausgang schalten und Pullup weglassen.
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.
Uups, das war wohl der falsche. Korrektur: DDRB |= (1<<SPI_SS) MfG
>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ß
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.