Hallo allerseits, für einen Kunden hab' ich eine Schaltung mit einem Tiny861 /AVR GCC entwickelt und nächste Woche will er diese in einem Gerät ausstellen, doch irgendwo ist der Wurm drin. Das Programm auf dem Controller scheint abzustürzen und zwar auf eine Art und Weise, die ich mir nicht aufgrund eines möglichen Fehlers im Code erklären kann. Das kleine Segment unten zeigt einen Code- Ausschnitt. Irgendwo im Programm wird ein Buzzer angesteuert, der eine Tonfolge ausgibt. Der Aufruf der beiden "play_tone" Funktionen erfolgt direkt hintereinander, sollte also auch durch einen Programmfehler nicht gestört werden können. Dennoch meldete der Kunde, dass das System eindeutig bei einem Ton hängen blieb und bis zum Reset der Schaltung andauernd den einen Ton ausgab. Dies passierte ein einziges Mal innert 10 Stunden Testzeit. Wie kann so etwas passieren? Deutet dies vielleicht auf einen Stack- Overflow hin und wie kann ich dies ausschliessen? Das Programm beinhaltet noch zwei ISRs: TIMER1_OVF sowie TIMER0_CAPT. Die Allokation aller Variablen wurde dem GCC überlassen; es sollte also nicht zu Ueberlappungen kommen. Kann es sein, dass ich beim Compilieren etwas falsch einstellte? Die eingestellten Optionen, siehe ganz unten in dieser Mail. Was könnte es sonst sein? Vielen herzlichen Dank für jede Hilfe! Gruss, Tobias _____________________________________________________ //Buzzer an PA2 #define BUZZER_INV PORTA ^= 0x04 #include <util/delay.h> .... if(...){ play_tone(249, 84.9); play_tone(264, 73.5); } ... void play_tone(unsigned int length, double period){ do{ _delay_us(period); BUZZER_INV; } while(length--); BUZZER_OFF; //switch off buzzer } _____________________________________________________ -gdwarf-2 -std=gnu99 -Wall -mcall-prologues -DF_CPU=8000000UL -O2 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums (O2, da der Speicher langsam knapp wird)
Bei so seltenen Abstürzen: Hardware I.O? Abblockkondensatoren vorhanden? Ansonsten: _delay_us darf nur mit KONSTANTEN Parametern aufgerufen werden, sonst delay'ed der VIEL zu lange, weil er intern haufenweise float-berechnungen macht. => Dokumentation zu _delay_us durchlesen! Würde auch erklären warum dein Flash schon bald voll ist.
Danke für die wertvolle Hilfe! Dass der Delay falsche Zeiten erzeugt, ist mir damals auch aufgefallen. Da ich damit aber nur diese Töne erzeuge, untersuchte ich das vorerst nicht genauer und irgendwann dachte ich nicht mehr an diese Unstimmigkeit; es funktionierte ja irgendwie (!) und ich kümmerte mich um anderes. Werd' ich aber dringend ändern - ist vielleicht der Grund für das Desaster... Der Controller wird mit 5V aus einem 7805 gespiesen, direkt neben den VCC / GND Pins befinden sich 100nF, SMD. AGND und AVCC sind auf dem kürzesten Weg mit den GND / VCC Pins verbunden. Auf dem Board gibt sicher es keine grossen Störquellen. Danke und Gruss, Tobias
BOD und/oder Watchdog aktiviert? Könnte auch noch helfen. Damit kann der Controller zwar immer noch "abstürzen", jedoch nicht durch Einbrüche der Spannungsversorgung (BOD) und nach einer bestimmten Zeit wird er korrekt zurückgesetzt (Watchdog).
Danke auch! Die Schaltung läuft an 5V, der BOD ist auf 4V3 gesetzt. Auch dein Tipp mit dem Watchdog ist gut. Der Watchdog ist aber bewusst noch nicht aktiv. Ich möchte ihn erst aktivieren (und im Programm behandeln), wenn das System absturzfrei läuft. Inzwischen ruf' ich die _delay_us Routine nur noch mit Konstantem Parameter auf. Der Aufruf mit einer Variablen hat tatsächlich etwa 2kB Code erzeugt. Ja.. ich kann mich noch dran erinnern, wie ich mich fragte, ob mein Projekt nicht mal kleiner war... Man lernt nie aus... Gruss, Tobias
Natürlich hilft der Watchdog nicht gegen die Abstürze, doch er bietet eine Möglichkeit, den Controller zu "retten" und herauszufinden, was die Absturzursache war. Du könntest beispielsweise beim normalen Programmstart den ganzen SRAM mit einem Bitmuster überschreiben (z.B. 0x55 oder so) und beim Reset durch den Watchdog über eine Schnittstelle ausgeben. Dann solltest du erkennen können, ob ein Stapelüberlauf ein Problem ist. Das muss aber natürlich alles vor dem eigentlichen C-Programmstart passieren, also am Besten in .init0, gegebenenfalls mit Inline-ASM.
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.