Forum: Mikrocontroller und Digitale Elektronik ATMega328, komisches Verhalten bei fast vollem Speicher


von Sebastian M. (cyberseb)


Lesenswert?

Hallo zusammen,

nun habe ich mein recht umfrangreiches Programm endlich fast fertig, 
wird der Speicher knapp. AVR-GCC sagt:

Device: atmega328p

Program:   32410 bytes (98.9% Full)
(.text + .data + .bootloader)

Data:       1905 bytes (93.0% Full)
(.data + .bss + .noinit)


Optimieren kann ich den Code sicher noch, wird aber sehr schwierig. Ich 
habe schon - soweit es mir möglich war - alle Register gezogen. Mit 
PROGMEM habe ich experimentiert, das macht unter Data einiges frei, 
allerdings brauche ich dafür extra Programmlogik für die wenig Platz 
ist. Und am Verhalten konnte ich auch keine Veränderungen feststellen.

Das Seltsame: Flashe ich den Controller mit dem AVR-ISP II neu, startet 
der Microcontroller einwandfrei und arbeitet das Programm ab. Nach einem 
Reset ist er (meistens!) allerdings wie tot oder startet "seltsam" (z.B. 
mit Verzögerung).

Das Programm gibt direkt am Anfang von main() einen Text auf einem LCD 
aus.

Das nicht reproduzierbare Verhalten tritt schon auf, bevor der 
Controller überhaupt diese Nachricht anzeigt. Man sieht dann lediglich 
einen schwarzen Balken auf dem LCD.

Warum funktioniert das Programm dann aber nach dem Flaschen ohne 
Probleme?

Über Tipps würde ich mich sehr freuen, ich würde nur ungern auf einen 
anderen Controller (ATMega644) umsteigen ... Platinenlayout is schon 
fertig und es ist kaum noch Platz für einen größeren Controller ... :-/

Viele Grüße
Sebastian

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

Wie geht es deinem Stack?

von Tom (Gast)


Lesenswert?

Du musst zu allererst auch bedenken, dass die RAM-Angabe sich rein auf 
globale Variablen bezieht. Du brauchst noch RAM für lokale Variablen, 
Stack, ...
Wenn voll, dann voll und dann passieren komische Dinge.

von Fritz G. (fritzg)


Lesenswert?

Es könnte am RAM liegen. Du hast etwas über 100 Bytes frei, reicht das 
für lokale Variablen und Stack?
Sollte der Mega644 nicht pinkompatibel sein?

von Carsten R. (kaffeetante)


Lesenswert?

Bislang wurden für das Fehlverhalten nur Symptome am Display genannt. 
Kannst du auch an anderen Komponenten Fehlfunktionen erkennen? Es kann 
auch ein Timingproblem bei der Initialisierung des Displays sein, so daß 
es mal unter bestimmten Vorbedingungen funktioniert und unter anderen 
Bedingungen nicht mehr. Hast du eine oder mehrer Diagnose-LED oder einen 
seriellen Anschluß als Kontrollmöglichkeit?

So Allgemein beschrieben ist eine zuverlässige Diagnose unmöglich! Da 
hilft nur ein systematischer Test, Komponente für Komponente. Ein "es 
funktioniert nicht" ist keine brauchbare Fehlerbeschreibung.

: Bearbeitet durch User
von Tom (Gast)


Lesenswert?

Es gibt hier irgendwo einen Codeschnipsel, mit dem man im laufenden 
Betrieb den Minimalwert des noch freien RAMs bestimmen kann. Wenn da 0 
rauskommt, braucht man eigentlich gar nicht weitersuchen.

von Fritz G. (fritzg)


Lesenswert?

1
int freeRam (void) {
2
    extern int __heap_start, *__brkval;
3
    int v=(int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
4
    return v;
5
}

von Sebastian M. (cyberseb)


Lesenswert?

Hallo zusammen,

herzlichen Dank für Euer Feedback!!!

Ich werde mit Euren Tipps heute Abend auf Fehlersuche/Optimierung gehen. 
Ich werde den Speicherverbrauch messen und mal konsequent alles auf 
PROGMEM umstellen.

Das mit der LCD-Initialisierung könnte auch stimmen. Denn da drüber 
scheint der Controller nicht zu kommen. Wobei es auch sein könnte, dass 
er gar nicht bis dahin kommt, denn das ist eigentlich das erste, was das 
Programm macht. Vielleicht ist der Speicher so voll, dass das eine 
Auswirkung auf das Timing hat.

Mir ist es nur ein Rätsel, warum alles nach einem Reset durch den 
AVR-ISP (augenscheinlich) einwandfrei funktioniert. Incl. Timer, PWM, 
EEPROM-Funktionen, usw. ... Also am Stack oder lokalen Variablen kann 
das eigentlich nicht liegen.

Zum Debuggen habe ich ein Oszi, da sollte sich evtl. was machen lassen.

Ich kann den Code auch über Preprozesser-Direktiven auf eine serielle 
Ausgabe umkonfigurieren (damit läuft die Firmware auf einem Arduino), 
allerdings sind da einige Funktionen deaktiviert und der 
Speicherverbrauch ist deutlich niedriger ...

Echt komisch, dieses nichtdeterministische Verhalten. Wirklich wohl ist 
mir bei der Sache nicht! Vielleicht sollte ich das Ding als 
Zufallszahlengenerator einsetzen. ;-)

Viele Grüße
Sebastian

von Stefan F. (Gast)


Lesenswert?

Kommentier irgendwas optionales auf (z.B. die Display-Ausgabe). Wenn das 
Programm dann stabil läft, hast du warscheinlich einen Stack-Überlauf 
(also zu viel RAM belegt).

von Sebastian V. (sebi_s)


Lesenswert?

Das dein Programm direkt nach dem Flashen scheinbar ordnungsgemäß 
funktioniert deutet eher nicht auf einen Stackoverflow hin. Klingt eher 
nach nicht initialisierem Speicher oder sowas.

von Peter D. (peda)


Lesenswert?

Sebastian M. schrieb:
> Flashe ich den Controller mit dem AVR-ISP II neu, startet
> der Microcontroller einwandfrei und arbeitet das Programm ab. Nach einem
> Reset ist er (meistens!) allerdings wie tot oder startet "seltsam" (z.B.
> mit Verzögerung).

Unterschiede im Startverhalten sind meist Initialisierungsfehler 
(Reihenfolge, Zeitabläufe).

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Sebastian M. schrieb:
> Optimieren kann ich den Code sicher noch, wird aber sehr schwierig.

Aus Erfahrung kann ich Dir sagen, dass man da noch jede Menge rausholen 
kann. Das fängt schon bei den Compiler-Optionen an (z.B. flto). 
Wahrscheinlich magst Du Dein Programm hier nicht posten, aber ich bin 
mir sicher, dass man 20-50% immer noch rausholen kann, wenn da mal ein 
anderer auf den Code schaut.

Ich tippe nämlich auch auf einen Stacküberlauf - oder auf einen 
Überschreiber im RAM.

: Bearbeitet durch Moderator
von Mein grosses V. (vorbild)


Lesenswert?

Sebastian M. schrieb:
> Ich habe schon - soweit es mir möglich war - alle Register gezogen.

Benutzt du hauptsächlich int statt char?
Viele globale Variable? Lokale Variable werden nur dann angelegt, wenn 
sie auch beötigt werden. Danach ist der Speicher wieder frei.

Und eine ganze dumme Frage: Ist die Optimierung eingeschaltet?

Sebastian M. schrieb:
> Das Programm gibt direkt am Anfang von main() einen Text auf einem LCD
> aus.

Sebastian M. schrieb:
> Das Programm gibt direkt am Anfang von main() einen Text auf einem LCD
> aus.

Bei der Länge von Texten sollte man sich auch einschränken. Meistens 
sind einzelne Zeichen oder wenigstens Abkürzungen genauso 
aussagekräftig.

von S.Siebenhaar (Gast)


Lesenswert?

Die Routinen, die für den Zugriff auf PROGMEM benötigt werden sind nicht 
besonders umfangreich. Das hast Du bereits nach ein paar Zeilen Text 
wieder reingeholt.

Auch wenn Du darauf achtest, dass DEINE Routinen schonend mit dem Stack 
umgehen, muss das nicht heißen, das es fertige, eingeblendete 
Fremdroutinen, auch tun.

Wie von anderen gesagt: Die Speicherberechnung erfasst nur den 
"offensichtlichen" Speicher. Nicht den in den Routinen temporär 
reservierten, und nicht den Stack. Besonders lecker ist eine Rekursion.

Viele Programmierer sichern, nach dem Einsprung in ihre Routinen, alle 
Register, die sie plattmachen. Egal ob Du sie nutzt oder nicht. Eine 
5-fache Verschachtelung von Unterroutinen mit jeweils 5 gesicherten 
Registern ergibt ohne den program counter 25 Byte die keiner kennt. Ups!

Diese Programmierroutine ist aber nicht unbedingt als Fehler anzusehen, 
sondern eher als Reflex.

von Falk B. (falk)


Lesenswert?

@  Sebastian M. (cyberseb)

>Das Seltsame: Flashe ich den Controller mit dem AVR-ISP II neu, startet
>der Microcontroller einwandfrei und arbeitet das Programm ab. Nach einem
>Reset ist er (meistens!) allerdings wie tot oder startet "seltsam" (z.B.
>mit Verzögerung).

>Das Programm gibt direkt am Anfang von main() einen Text auf einem LCD
>aus.

>Das nicht reproduzierbare Verhalten tritt schon auf, bevor der
>Controller überhaupt diese Nachricht anzeigt. Man sieht dann lediglich
>einen schwarzen Balken auf dem LCD.

Das ist kein Speicherproblem sondern ein Initialisierungsproblem, dann 
zu diesem Zeitpunkt sind ja noch keine großen Funktionen aufgerufen 
worden. Wahrscheinlich fehlt ein Delay am Anfang, um das LCD korrekt zu 
initialisieren. Vielleicht fehlt auch nur das Einschalten das Brown Out 
Detektors bzw. einer großen Startup Zeit (AVR Fuses), damit die CPU erst 
bei ausreichend Spannung losläuft. Das kann vor allem im Zusammenhang 
mit dem LCD ein Problem sein. Der Controller kann auch mit 1,8V korrekt 
arbeiten und rennt los, das LCD kann das nicht.

von Sebastian M. (cyberseb)


Lesenswert?

Hallo zusammen,

danke für Eure Tipps! Jetzt geht es weiter ...

Also, ich habe das Problem auf einem zweiten Gerät reproduziert. An ein 
(einfaches) Initialisierungsproblem glaube ich nicht - es hängt 
definitiv mit dem Speicher zusammen.

Ob es geht, oder nicht, ist von diesen zwei Codezeilen abhängig. Und die 
sind mitten im Code, weit, weit weg von der Initialisierung:

   screen_locate(1, 2);
   screen_print("(Speed restored)");

Kommentiere ich die aus, läuft alles. Sind sie drin, funktioniert das 
Programm direkt nach dem Flashen, aber nicht mehr nach einer 
Stromunterbrechung.

Die LCD-Initialisierung funktioniert sonst ohne jegliche Probleme. Ich 
könnte mir nur vorstellen, dass es evtl. aufgrund einer anderen 
Speicherinitialisierung (ausgelöst vom AVR-ISP) "irgendwie" doch 
funktionieren kann. Und mit dem o.g. Code startet das Programm auch 
manchmal (selten), aber verzögert (mit schwarzen Balken).

Tja, ich werde wohl experimentieren und weiter optimieren müssen. 
Diverse von Euch genannte Tipps hatte ich schon umgesetzt (z.B. CHAR 
statt INT), ebenso sich widerholende Aufrufe in Schleifen/Funktionen 
gepackt (hat alles ein paar Byte gebracht).

Jetzt werde ich das LCD mal "abschalten" und schauen, ob das Programm 
soweit läuft. Ebenso werde ich mal testhalber Codeblöcke deaktivieren.

Den Code möchte ich nicht zeigen, da es eine Firmware für ein DIY-Kit 
werden soll. Nicht um richtig Geld zu machen, sondern um Geld in die 
Hobby-Kasse zurückfließeb zu lassen. Darum gibt es auch eine freie 
Arduino-Version für die DIY-Community.

Wen es interessiert, es geht um einen frequengeregelten Sinus-Inverter 
zur Geschwindigkeitsregelung von Plattenspielern: 
http://mate-labs.de/magicquartz/

Viele Grüße
Sebastian

von Sebastian M. (cyberseb)


Lesenswert?

Jupp - nehme ich einen Programmteil raus (direkt mit einem "return;" am 
Anfang einer größeren Funktion), funktioniert es einwandfrei.

Es liegt also am Speicherverbrauch!

Das Verhalten mit dem Reset durch den AVR-ISP macht mich aber ganz kirre 
...

Gruß, Sebastian

von Gerhard (Gast)


Lesenswert?

Schönes Projekt, gefällt mir sehr!

von Tom (Gast)


Lesenswert?

Mach mal eine Ausgabe des aktuell freien Speichers (auf das Display) 
rein. Dann siehst du gleich deine Fortschritte.

von M. K. (sylaina)


Lesenswert?

Sebastian M. schrieb:
> screen_print("(Speed restored)");

Hast du mehrere Code-Zeilen dieser Art? Speicher kannst du dann sparen 
indem du den String im Flash lässt und dir eine screen_print-Variante 
schreibst, die auch einen String aus dem Flash schreiben kann, z.B.:
1
//fuer den Zugriff auf den Flashspeicher
2
#include <avr/pgmspace.h>
3
...
4
screen_print_p(PSTR("(Speed restored)");
5
...
6
//funktion zum Schreiben von Strings aus dem Flash
7
void screen_print_p(const char* stringFromFlash) {
8
  register char zeichen;
9
    while( zeichen = pgm_read_byte(stringFromFlash++) ) {
10
      //lcd_put_char sei die Funktion, die generell nur ein Zeichen schreibt.
11
      screen_print_char(zeichen);
12
    }
13
}
14
...
Auf ähnliche Weise kann man auch das EEPROM nutzen wenn man es sonst 
nicht braucht, der RAM aber knapp wird.

: Bearbeitet durch User
von Sebastian M. (cyberseb)


Lesenswert?

Hallo zusammen,

@Gerhard: danke, das freut mich!!!

@Tom: Um die 450-500 Bytes sind jetzt frei im Betrieb nach der von 
sylaina vorgeschlagenen Änderung.

@sylaina: Gerade gemacht, danke! Ich bekomme jetzt:

  Program:   32468 bytes (99.1% Full)
  (.text + .data + .bootloader)

  Data:       1517 bytes (74.1% Full)
  (.data + .bss + .noinit)

Das hat wohl einiges gebracht.

Aber - trotz der ganzen Änderungen am Programmcode - ändert das am 
Verhalten absolut nichts! Sobald ich das hier einbaue ...

   screen_locate(1, 2);
   screen_print("(Speed restored)");

... startet das Ding nicht mehr. Ich habe schon versucht die Klammern zu 
ersetzen (man weiß ja nie?) und ein Delay vor die LCD-Init-Routine 
gepackt, bringt alles nichts.

Das muss irgendwie mit dem Speicher zusammenhängen. Mir wird wohl nichts 
anderes übrig bleiben, den Code kleiner zu bekommen.

Vielleicht sollte ich das EEPROM-Wearleveling (wird von Zeit zu Zeit um 
ein Byte weitergeschoben) raushauen, das wird keinen stören! ;-)

Viele Grüße
Sebastian

von Sebastian M. (cyberseb)


Lesenswert?

Hmmm, mit

  screen_locate(1, 2);
  screen_print_p(PSTR("(Speed restored)"));

funktioniert das Ding wiederum. Krank!

Gruß, Sebastian

von Falk B. (falk)


Lesenswert?

@ Sebastian M. (cyberseb)

>Aber - trotz der ganzen Änderungen am Programmcode - ändert das am
>Verhalten absolut nichts! Sobald ich das hier einbaue ...

>   screen_locate(1, 2);
>   screen_print("(Speed restored)");

>... startet das Ding nicht mehr.

Tja, es ist immer noch ein Initialisierungsproblem ;-)

> Ich habe schon versucht die Klammern zu
>ersetzen (man weiß ja nie?) und ein Delay vor die LCD-Init-Routine
>gepackt, bringt alles nichts.

>Das muss irgendwie mit dem Speicher zusammenhängen.

Nö. Du hast doch gerade das GEGENTEIL bewiesen!!

> Mir wird wohl nichts
>anderes übrig bleiben, den Code kleiner zu bekommen.

Nö. Einfach mal nachdenken und eine systematische Fehlersuche 
betreiben.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sebastian M. schrieb:
> Das Seltsame: Flashe ich den Controller mit dem AVR-ISP II neu, startet
> der Microcontroller einwandfrei und arbeitet das Programm ab. Nach einem
> Reset ist er (meistens!) allerdings wie tot oder startet "seltsam" (z.B.
> mit Verzögerung).

 Und wenn die Versorgung fur 1-2 Minuten abgeschaltet wird ?

 Nach RESET werden nur die I/O Register auf Initial Values gesetzt -
 aber RAM bleibt unverandert.
 Ich glaube, dass irgendeine Routine (deine oder Library) falsch
 annimmt, dass irgendeine RAM-Adresse auf 0 ist.

 Nach flashen oder Stromabschalten stimmt das auch, aber nach einem
 RESET nicht.

 P.S.
  Check mal:   ' screen_print("(Speed restored)"); '
 (Assembler listing)

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@  Marc Vesely (Firma: Vescomp) (logarithmus)

> Ich glaube, dass irgendeine Routine (deine oder Library) falsch
> annimmt, dass irgendeine RAM-Adresse auf 0 ist.

Nicht unbedingt 0, ggf. aber ein SINNVOLLER Wert.

> Nach flashen oder Stromabschalten stimmt das auch,

Nein. Nach einem Power Up Oder Flashen ist der SRAM ebenso undefiniert. 
Er kann aber besonders beim Flashen durch das vorherige Programm auf 
einen zufällig brauchbaren Wert gesetzt worden sein.

>  Check mal:   ' screen_print("(Speed restored)"); '

Ja.

> (Assembler listing)

Nein. Der Fehler liegt mit an Sicherheit grenzender Wahrscheinlichkeit 
NICHT im Compiler oder Assembler sondern beim Entwickler der Funktionen. 
Eine Sichtung des C-Quelltextes reicht vollkommen aus. Und man sollte 
die Compilerwarnungen ernst nehmen. Sowas wie "variable x may be 
uninitialized" ist sowas. Im Zweiflesfall setzt man ALLE lokalen 
Variabelen bei der Definition in der Funktion erstmal auf 0.

1
int x = 0;

von Sebastian M. (cyberseb) (Gast)


Lesenswert?

Hallo zusammen,

oha - jetzt wird es interessant!

Ich will den Fehler undbedingt finden, aus Interesse. Leider habe ich 
den problematischen Code nicht gesichert (ich Depp), aber der sollte 
sich aus dem backup vom Vortag wieder herstellen lassen. Viel hatte ich 
nicht geändert seit dem.

Also an unitialisierten Variablen liegt es nicht. Es gibt auch keine 
Compiler-Warnungen.

Und der o.g. Codeschnipsel ist m.E. auch nicht direkt schuld an dem 
Problem, da der bei dem von mir beschriebenen Fehlverhalten gar nicht 
ausgeführt wird (auch nicht zwischen dem Neustart). Der ist "tief" im 
Code vergraben und muss explizit vom User über eine Funktion aufgerufen 
werden.

Ich glaube eher, dass das Problem auftritt, wenn die Programmgröße einen 
gewissen Wert überschreitet.

Vielleicht liegt es doch am Compiler. Ich glaube ich verwende eine 
ältere Version von 2012 oder 2013, weil mit der aktuellen mein Eclipse 
Probleme hatte, den ATMega328 korrekt zu erkennen.

Heute Abend gehts weiter - aber viel Hoffnung, das zu finden, habe ich 
nicht ... :-/

Gruß, Sebastian

von Axel R. (Gast)


Lesenswert?

tolles projekt.
Ich hatte seinerzeit eine dds (32.5kHz) aufgesetzt, die 60hz Sinus 
erzeugt und das über Mosfettreiber / Halbbrücken mit einem Printtrafo 
auf 110Volt hochtransformiert. Spielt (im "Schuhkarton") ganz toll, war 
ruckzuck fertig und spielte etwas Geld in die Hobbykasse zurück.
man kann die Sache aber auch aufblasen und natürlich auch n Display 
anschliessen  :)

Axelr.
DG1RTO

von Falk B. (falk)


Lesenswert?

@Sebastian M. (cyberseb) (Gast)

>Ich will den Fehler undbedingt finden, aus Interesse.

Gut!

>Leider habe ich
>den problematischen Code nicht gesichert (ich Depp),

Schlecht!

>Also an unitialisierten Variablen liegt es nicht. Es gibt auch keine
>Compiler-Warnungen.

Sind die alle eingeschaltet?

>Und der o.g. Codeschnipsel ist m.E. auch nicht direkt schuld an dem
>Problem, da der bei dem von mir beschriebenen Fehlverhalten gar nicht
>ausgeführt wird (auch nicht zwischen dem Neustart).

Dannhast du uns aber schön veralbert!

>Ich glaube eher, dass das Problem auftritt, wenn die Programmgröße einen
>gewissen Wert überschreitet.

Welche theoretische Überlegung würde denn DAFÜR sprechen?
Du macht hier genau das Gegenteil einer systematischen Fehlersuche. Du 
stellt wilde Theorien ohne Begründung auf. :-(

>Vielleicht liegt es doch am Compiler.

Möglich, aber unwahrscheinlich.

>Heute Abend gehts weiter - aber viel Hoffnung, das zu finden, habe ich
>nicht ... :-/

Mit DER Einstellung sicher nicht.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Falk B. schrieb:
>>  Check mal:   ' screen_print("(Speed restored)"); '
>
> Ja.
>
>> (Assembler listing)
>
> Nein. Der Fehler liegt mit an Sicherheit grenzender Wahrscheinlichkeit
> NICHT im Compiler oder Assembler sondern beim Entwickler der Funktionen.

 Genau das habe ich auch behauptet.
 'screen' wird (auch wenn er erst später aufgerufen wird) am Anfang
 initialisiert.
 Wie das alles genau gemacht wird und was 'screen_print' für sich
 reserviert und danach erwartet, sieht man nur aus Assembler listing.

Sebastian M. (cyberseb) schrieb:
> Ich glaube eher, dass das Problem auftritt, wenn die Programmgröße einen
> gewissen Wert überschreitet.

 Na dann mache mal eine Dummy-Funktion, die genauso lang ist wie
 'screen', werfe 'screen' raus und...
 Wetten, dass es keine Probleme mehr gibt ?

: Bearbeitet durch User
von Sebastian M. (cyberseb) (Gast)


Lesenswert?

@Falk:

>>Also an unitialisierten Variablen liegt es nicht. Es gibt auch keine
>>Compiler-Warnungen.
>
> Sind die alle eingeschaltet?

Standard-Einstellungen. Ich schaue mal, ob sich da noch etwas machen 
lässt! Guter Tipp - danke!

>>Und der o.g. Codeschnipsel ist m.E. auch nicht direkt schuld an dem
>>Problem, da der bei dem von mir beschriebenen Fehlverhalten gar nicht
>>ausgeführt wird (auch nicht zwischen dem Neustart).
>
> Dannhast du uns aber schön veralbert!

Warum denn? Ich hatte oben doch klar geschrieben, dass dieser Code weit 
weg von der Initialisierung ist. Sorry, falls ich da nicht präzise genug 
war - als Hilfesuchender möchte ich Euch auf keinen Fall veralbern!

>>Ich glaube eher, dass das Problem auftritt, wenn die Programmgröße einen
>>gewissen Wert überschreitet.
>
> Welche theoretische Überlegung würde denn DAFÜR sprechen?
> Du macht hier genau das Gegenteil einer systematischen Fehlersuche. Du
> stellt wilde Theorien ohne Begründung auf. :-(

Halten wir fest, die Fakten:

- Der Code hat scheinbar Auswirkungen auf das Programmverhalten, obwohl 
er gar nicht ausgeführt wird.
- Es macht einen Unterschied, ob der Controller vom AVR-ISP geflasht und 
resettet wird oder er per Stromunterbrechung neu startet.

Daraus folgen meine Überlegungen:

Der o.g. C-Code macht das Programm größer. Teile des Binärcodes landen 
an anderen Stellen im Flash. Allerdings sollte das keinen Einfluss auf 
das Initialisieren von irgendwelchen Variablen (die ich ja eh alle 
initialisiere) oder auf das Timing in der LCD-Initialisierung haben. Das 
könnte vielleicht wirklich ein Compiler-Bug sein. Andererseits glaube 
ich das aber nicht (unwahrscheinlich) und das Verhalten im Zusammenhang 
mit dem AVR-ISP spricht auch dagegen.

M.E. ist es kein einfaches Initialisierungsproblem des LCDs - die 
Routine hat immer einwandfrei funktioniert. Es muss irgend ein Mist im 
RAM liegen (Werte von Variablen), die es verhindern, dass das Programm 
über die LCD-Initialisierung kommt.

Wie würdest Du denn dann "systematisch" vorgehen? Ich werde heute Abend 
noch ein paar von Euren Vorschlägen durchgehen.

@DG1RTO: Danke! Ja, das Ding ist wirklich aufgeblasen, da hast Du Recht. 
:-)

Gruß, Sebastian

von Falk B. (falk)


Lesenswert?

@  Sebastian M. (cyberseb) (Gast)

>Wie würdest Du denn dann "systematisch" vorgehen?

Hab ich das nicht schon mehrfach getan?

Zuerst mal die Brown Out Fuse setzen, ebenso die längste Wartezeit für 
den Oszillator (beim 328er glaub ich 64ms).
Damit ist die Spannungsversorgung für das LCD! schon mal OK, wenn das 
Programm losläuft.

Dann kann man mal den Großteil des Programms (im main) auskommentieren 
und nur die IO-Initialisierung und die fragliche Funktion stehen lassen 
und testen.
ICh vermute, daß dann das Problem immer noch da ist.

von Carsten R. (kaffeetante)


Lesenswert?

So wird das nichts! Du hast dich entschieden zu glauben, daß es an der 
Codegröße liegt und willst das nun beweisen. Wenn der Fehler woanders 
liegt, kann dieses Vorgehen nur scheitern.

Die Code-Größe an sich hat definitiv keine Auswirkung auf das Problem. 
Allenfalls wenn der Programmspeicher nicht ausreichen würde, aber dann 
kommst du gar nicht erst soweit den Flashvorgang abzuschließen.

Allenfalls der Rambedarf könnte Einfluß haben, aber der hängt nicht mit 
der Codegröße zusammen! Außerdem ist der Rambedarf in der Regel nicht 
davon abhängig wie resettet wurde.

Allenfalls wenn du eine Routine hättest die den Resetgrund auswertet, 
könnte das Verhalten diesbezüglich unterschiedlich sein. Ansonsten ist 
das Verhalten des Codes/der Software immer die gleiche. Solange keine 
Eingaben in den Bootvorgang eingebaut werden, ist das Startverhalten 
dann immer identisch. Dann bleibt nur ein Unterschiedliches Verhalten 
der Hardware.

Gehe es systematisch durch.

Nehme alles raus bis auf die Displayroutinen und füttere die mit 
Dummydaten zur Ausgabe. Bleibt das Problem?

Suche eine alternative Ausgabemöglichkeit, Serieller Port, LED etc

Bevor wir mit On-Chip-debugging bzw JTAG loslegen würde ich im Program 
an den entscheiden Punkten eine Einfache Ausgabefunktion zur Kontrolle 
einfügen. Dann kannst du sehen wie weit das Programm kommt und ob die 
Reihenfolge und Inhalte der Ausgaben vom Erwarteten Verhalten abweichen.

Sebastian M. schrieb:
> Das Seltsame: Flashe ich den Controller mit dem AVR-ISP II neu, startet
> der Microcontroller einwandfrei und arbeitet das Programm ab. Nach einem
> Reset ist er (meistens!) allerdings wie tot oder startet "seltsam" (z.B.
> mit Verzögerung).

GANZ ENTSCHEIDENDE FRAGE
Was exakt verstehst du in diesem Falle unter einem Reset?

Strom aus, Strom an?
Strom aus, Pause, Strom an?
Benutzung eines Resettasters am Reset-Pin?
Oder oder oder...

Falls du einen Resettaster nutzt, wie ganau sie die komplette 
Beschaltung des Pins exakt und absolut vollständig bei dir aus?

Welches Display verwendest du?

: Bearbeitet durch User
von Sebastian M. (cyberseb)



Lesenswert?

Hallo Falk & Carsten (und alle),

danke weiterhin für Eure Hilfe - ich hoffe, dass bei der Sache 
wenigstens neue Erkenntnisse für das Forum herauskommen. (Ja, vermutlich 
sitzt das Problem vor dem Computer, aber ein Ideal-Standard-Fehler ist 
das glaube ich auch nicht ...)

Ihr habt Recht, meine Vorgehensweise bisher war sicher nicht 
systematisch genug. Vermutlich weil ich mit meinem Latein bei der Sache 
einfach am Ende bin.

Ich konnte einen älteren Code wiederherstellen, der das Problem hat. An 
dem Display-Aufruf (Codeschnipsel oben) liegt es hier nicht, es muss 
also etwas Anderes sein.

Viele der Dinge, die Ihr genannt habt, waren schon immer OK:

- Kein Watchdog
- Verwende Brown-Out-Detection
- Wartezeit auf Maximum

Und hier hast Du Dich geirrt, Falk: Kommentiere ich einen Codeblock in 
der main() aus (der niemals zur Auführung kommt und was das Programm 
kleiner macht), funktioniert es! Weiß der Kuckuck, warum.

Ich habe nun meine Tools (Eclipse AVR Plugin) und den Compiler 
geupdated. WOW, das hat noch einiges an der Programmgröße eingespart, 
mit dem Ergebnis, dass es mit allen Update-Kombinationen funktioniert.

Eclipse Alt + Compiler Alt: Fehler vorhanden
Eclipse Neu + Compiler Alt: OK
Eclipse Alt + Compiler Neu: OK
Eclipse Neu + Compiler Neu: OK

("Eclipse" meint hier das AVR-Plugin)

Die Ergebnisse hängen an. Was ich so gesehen habe, verwendet das Eclipse 
AVR Plugin z.B. die Optionen -ffunction-sections -fdata-sections. Aber 
das ist nicht alles; auch wenn ich diese deaktiviere, ist das Programm 
kleiner.

Dafür hat der neue Compiler doch noch uninitialisierte Variablen 
gefunden. Ich werde nun auf die Alt/Alt-Kombi zurückwechseln und 
weitertesten.

Viele Grüße, Sebastian

von Tom (Gast)


Lesenswert?

-Wall -Wextra

nicht vergessen. Der findet bestimmt noch ein paar Code-Probleme.

von Bernd K. (prof7bit)


Lesenswert?

Sebastian M. schrieb:
> Das Verhalten mit dem Reset durch den AVR-ISP macht mich aber ganz kirre
> ...

Dir ist schon bewußt daß der AVRISP einen häßlichen Bug hat der dafür 
sorgt daß eine Sekunde nach dem Einschalten nochmal grundlos ein Reset 
gegeben wird? Vielleicht erklärt das das seltsame Verhalten das Du beim 
Einschalten beobachtest. Stöpsel den mal ab und probier es ohne.

von Sebastian M. (cyberseb)


Lesenswert?

Tom, danke! -Wextra hat tatsächlich noch ein paar unbenutzte an 
Funktionen übergebene Parameter gefunden. Das dürfte den Code kleiner 
machen, aber das ursprüngliche Problem sollte das auch nicht lösen ... 
:-(

Bernd, ach, das ist ein Bug? (Man gewöhnt sich dran :-D) Leider startet 
der Mega ohne den ISP auch nicht ...

Also die uninitalisierten Variablen sind unkritisch. Einmal handelte es 
sich tatsächlich um ungenutzten Code (lustig, was für einen Mist man bei 
vielen kleinen Änderungen so produziert), das andere ist das Auslesen 
des ADCW-Registers in der ADC_Init()-Routine. Der Compiler weiß nicht, 
dass das nötig ist.

von Tom (Gast)


Lesenswert?

Ich glaube, Bernd meinte, du sollst mal händisch nach einer Sekunde 
einen Reset machen und gucken, ob es dann "anspringt".

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sebastian M. schrieb:
> Tom, danke! -Wextra hat tatsächlich noch ein paar unbenutzte an
> Funktionen übergebene Parameter gefunden. Das dürfte den Code kleiner
> machen, aber das ursprüngliche Problem sollte das auch nicht lösen ...
> :-(

 Willst du nicht hören oder ist das ignore ?
 Unbenutzte Parameter sind NICHT dein Problem, sondern Variablen die
 BENUTZT, aber vorher nicht initialisiert sind.
 Sogar die Reihenfolge der Variablendeklarationen kann dein Problem zum
 Verschwinden bringen.
 Von mir aus kannst du weiter stur annehmen, dass Compiler daran schuld
 ist und dein Program keine Initialisierungfehler enthält.
 Ich bin raus.

von Sebastian M. (cyberseb)


Lesenswert?

Marc,

ich habe keine uninitialisierten Variablen! Sorry, falls ich das nicht 
explizit gesagt habe. Natürlich versuche ich Eure Ratschläge und Tipps 
zu berücksichtigen und mich zu melden, aber ich kann auch nur Schritt 
für Schritt vorgehen ...

Jedenfalls danke für Deine Hilfe und Zeit!!!

Gruß, Sebastian

von Sebastian M. (cyberseb)


Lesenswert?

Nachtrag: Das mit "unitialisiert" von mir oben ist tatsächlich falsch.

---------------
../main.c: In function 'ADC_Init':
../main.c:815:15: warning: variable 'result' set but not used 
[-Wunused-but-set-variable]
  unsigned int result = 0;
---------------

Kommt von:

---------------
void ADC_Init(void) {
  unsigned int result = 0;
  ...
  result = ADCW;
}
---------------

Das hat nichts mit "uninitialisiert" zu tun, sondern dass die Variable 
nicht mehr verwendet wird, der GCC aber nicht weiß, dass ich ADCW 
auslesen muss.

Sorry, war mein Fehler. Ich will Euer Feedback absolut nicht ignorieren, 
sondern schätze die Zeit, die Ihr aufbringt, SEHR.

Gruß, Sebastian

: Bearbeitet durch User
von Tom (Gast)


Lesenswert?

Spätestens -Wextra aktiviert -Wuninitialized
Wenn da nix kommt (ich sehe oben in den angehängten Ausgaben nix), ist 
es scheinbar ok?

Oder verwendest du irgendwo __attribute__((section(".noinit"))) oder 
sowas?

von Carsten R. (kaffeetante)


Lesenswert?

Carsten R. schrieb:
> GANZ ENTSCHEIDENDE FRAGE
> Was exakt verstehst du in diesem Falle unter einem Reset?

Eine Antwort darauf wäre hilfreich. Ich habe das nicht ohne Grund fett 
geschrieben.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sebastian M. schrieb:
> ich habe keine uninitialisierten Variablen! Sorry, falls ich das nicht
> explizit gesagt habe. Natürlich versuche ich Eure Ratschläge und Tipps
> zu berücksichtigen und mich zu melden, aber ich kann auch nur Schritt
> für Schritt vorgehen ...

 Ok, dann vergiss FLASH und konzentriere dich auf RAM.
 Was ich mit Reihenfolge der Deklaration meinte, ist folgendes:
1
 int ArrPtr;
2
 int DummyArr[20];
3
 int SehrWichtigeVar1, SehrWichtigeVar2;
 kann sehr lange funktionieren, muss aber nicht.
1
 DummyArr[ArrPtr] = 12345;
 ist OK, wenn ArrPtr < 20 ist, was aber wenn ArrPtr > 20 ist ?
 Deine SehrWichtigeVar1 hat plotzlich einen Wert von 12345.

 Wenn du aber so deklarierst:
1
 int SehrWichtigeVar1, SehrWichtigeVar2;
2
 int ArrPtr;
3
 int DummyArr[20];
4
 int UnwichtigeVar1, UnwichtigeVar2;
 kann das sehr lange gut gehen und unentdeckt bleiben.

 So etwas wiederum:
1
 int SehrWichtigeVar1, SehrWichtigeVar2;
2
 int DummyArr[20];
3
 int ArrPtr;
4
 int UnwichtigeVar;
 kann richtiges Chaos verursachen - muss aber nicht.

Marc V. schrieb:
> Check mal:   ' screen_print("(Speed restored)"); '
>  (Assembler listing)

 Wie funktioniert diese Routine (wird RAM benutzt, wenn ja, wieviel RAM,
 woher, etc.)
 Nur als Beispiel - ich kenne dein Programm nicht.

EDIT:
 Soviel ich weiß, überprüft C die Arraygrenzen nicht, deswegen...

: Bearbeitet durch User
von Sebastian M. (cyberseb)


Lesenswert?

@Tom: -Wuninitialized sagt, dass alles OK ist.

@Carsten: "Strom aus, Pause, Strom an". Ich habe auch schon längere 
Pausen (mehrere Minuten) probiert, erfolglos.

Der Reset-Pin hängt über einen 10kOhm-Widerstand an VCC. Sollte 
eigentlich passen.

Als nächstes werde ich mal mit dem Oszi schauen, ob das Programm im 
Fehlerfall überhaupt irgendetwas macht. Könnte mit meinem alten Hameg 
205 schwierig werden.

@Marc: Danke für Deine anschauliche Erklärung! Ich kann nicht 100%ig 
ausschließen, dass ich in irgend einem Array einen derartigen Fehler 
habe. Werde ich prüfen.

Die Funktion screen_print() ist nichts Besonderes, sondern nur ein 
Wrapper, damit ich die Ausgabe auf die serielle Schnittstelle für die 
Arduino-Version umleiten kann:

1
void screen_print(const char *s) {
2
#ifdef LCDDISPLAY
3
  lcd_text((u8*) s);
4
#endif
5
#ifdef SERIAL
6
  uart_puts(s);
7
#endif
8
}
9
10
...
11
12
void lcd_text(u8 *t) {
13
  while (*t) {
14
    lcd_data(*t);
15
    t++;
16
  }
17
}

Das ASM-Listing kann ich auch noch liefern, aber bis Sonntag ist erstmal 
Schluss (geht nicht, bin bei der Family eingespannt ...).

Viele Grüße
Sebastian

von M. K. (sylaina)


Lesenswert?

Marc V. schrieb:
> Was ich mit Reihenfolge der Deklaration meinte, ist folgendes:
>  int ArrPtr;
>  int DummyArr[20];
>  int SehrWichtigeVar1, SehrWichtigeVar2;  kann sehr lange funktionieren,
> muss aber nicht.
>  DummyArr[ArrPtr] = 12345;
>  ist OK, wenn ArrPtr < 20 ist, was aber wenn ArrPtr > 20 ist ?
>  Deine SehrWichtigeVar1 hat plotzlich einen Wert von 12345.

Frage interessehalber: Wenn DummyArr nur 20 Felder lang ist, sollte der 
Compiler doch meckern wenn man versucht auf Feld 20 oder größer 
zuzugreifen, oder? Also zumindest bei mir sagt dann der Compiler (ist 
"nur" ein Warning): Array subscript is above array bounds.
OK, ich hab auc -Werror an und entferne auch alle Warnings.

von Falk B. (falk)


Lesenswert?

@Sebastian M. (cyberseb)

>Als nächstes werde ich mal mit dem Oszi schauen, ob das Programm im
>Fehlerfall überhaupt irgendetwas macht. Könnte mit meinem alten Hameg
>205 schwierig werden.

Dazu braucht man kein Oszi. Eine LED kann man immer blinken lassen, auch 
so langsam, das man als Mensch was sieht. Z.B. nach jedem größeren 
Funktionsblock die LED toggeln.

>Das ASM-Listing kann ich auch noch liefern,

Das interessiert keinen. Poste VOLLSTÄNDIGEN Code als Anhang. Siehe 
Netiquette.

von Bernd K. (prof7bit)


Lesenswert?

M. K. schrieb:
> Frage interessehalber: Wenn DummyArr nur 20 Felder lang ist, sollte der
> Compiler doch meckern wenn man versucht auf Feld 20 oder größer
> zuzugreifen, oder?

Das kann der Compiler nur in den alleroffensichtlichsten Fällen 
feststellen, wenn überhaupt. Der Compiler wird jedoch NICHT versuchen 
das Programm solange zu simulieren bis er alle möglichen Werte von allen 
Variablen zu irgendeinem späteren Zeitpunkt kennt, das ist nicht 
praktikabel oder stellenweise gar nicht möglich. Nur offensichtliche 
Sachen die er in kürzester Zeit vollständig beweisen kann werden 
angemeckert.

Es gibt jedoch Compiler die können (auf expliziten Wunsch) 
Laufzeit-Checks in den Code einbauen wenn Array-Grenzen, Stack-Grenzen 
oder andere Grenzen überschritten werden und dann an Ort und Stelle 
unverzüglich eine aussagekräftige Laufzeitfehlermeldung werfen bevor 
es im halbzerstörten Zustand noch 2 Minuten weiterläuft und dann erst 
crasht. Aber sowas geht natürlich auf die Performance und auf die 
Codegröße.

Und ich wüßte jetzt auch nicht ob der gcc das überhaupt kann oder 
irgendein ein anderer C-Compiler, ich kenn das von verschiedenen Pascal 
Compilern, sowohl historischen als auch aktuellen, da war das schon 
immer ein bemerkenswertes optionales Zusatz-Feature das es von den 
meisten anderen Compilersprachen unterschied.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Falk B. schrieb:
>>Das ASM-Listing kann ich auch noch liefern,
>
> Das interessiert keinen. Poste VOLLSTÄNDIGEN Code als Anhang. Siehe
> Netiquette.

 Warum so ausschliesslich ?
 Mich würde das (vielleicht) interessieren.
 Vielleicht auch nicht...

 Oder doch ?

 Posten geht heutzutage ziemlich einfach, man muß es nicht selbst
 zum Forum tragen, also ja, kannst posten.

 Oder auch nicht, wie du willst...

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bernd K. schrieb:
> Und ich wüßte jetzt auch nicht ob der gcc das überhaupt kann oder
> irgendein ein anderer C-Compiler, ich kenn das von verschiedenen Pascal
> Compilern, sowohl historischen als auch aktuellen, da war das schon
> immer ein bemerkenswertes optionales Zusatz-Feature das es von den
> meisten anderen Compilersprachen unterschied.

 Und natürlich die Klarheit, Übersichtlichkeit etc.
 Auch nach Monaten (oder Jahren) weiss man noch, was da läuft, im
 Gegensatz zu manch anderen Sprachen (wer hat was von C gesagt ?)

von Carsten R. (kaffeetante)


Lesenswert?

Sebastian M. schrieb:
> @Carsten: "Strom aus, Pause, Strom an". Ich habe auch schon längere
> Pausen (mehrere Minuten) probiert, erfolglos.

Das ist kein Reset sondern ein Neustart. Der Reset des Programmerst 
zupft einmal an der Resetleitung, während die Spannung stabil bleibt. 
Viele ICs erwarten vorab eine Pause nachdem de Spannung stabil ist, 
bevor initialisiert werden kann. Du merkst an dieser Stelle den 
Unterschied zwischen dem Reset durch den Programmer und deinem "reset"?

Noch einmal:
Welches Display wird verwendet?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Carsten R. schrieb:
> bevor initialisiert werden kann. Du merkst an dieser Stelle den
> Unterschied zwischen dem Reset durch den Programmer und deinem "reset"?

 Kläre mich auf, bitte.

von Carsten R. (kaffeetante)


Lesenswert?

Carsten R. schrieb:
> Sebastian M. schrieb:
>> @Carsten: "Strom aus, Pause, Strom an". Ich habe auch schon längere
>> Pausen (mehrere Minuten) probiert, erfolglos.
>
> Der Reset des Programmerst
> zupft einmal an der Resetleitung, während die Spannung stabil bleibt

von M. K. (sylaina)


Lesenswert?

Marc V. schrieb:
> Kläre mich auf, bitte.

Hat er schon gemacht. Etwas genauer:

Bei deinem Reset mit Strom aus, Pause, Strom an sind bis zum 
Programmstart möglicher Weise noch nicht alle Baugruppen (UART, ADC und 
Co) im µC mit ausreichend Spannung versorgt, auch das LCD ist 
möglicherweise noch nicht bereit wenn der µC die ersten Befehle an das 
LCD schickt.

Wenn der ISP den µC resetet wird im Prinzip nur der Befehlszeiger wieder 
an den Start gesetzt, aber alle Komponenten sind da schon startklar.

von Carsten R. (kaffeetante)


Lesenswert?

M. K. schrieb:
> Frage interessehalber: Wenn DummyArr nur 20 Felder lang ist, sollte der
> Compiler doch meckern wenn man versucht auf Feld 20 oder größer
> zuzugreifen, oder?

Nein, der Compiler kann das im Allgemeinen nicht, bzw nur unter 
bestimmten Voraussetzungen, z.B. wenn du beim Kompilieren den Zugriff 
mit einem konstanten Index im Code stehen hast. Es muß zum Zeitpunkt des 
kompilierens schon erkennbar sein, daß ein Zugriff außerhalb der Grenzen 
erfolgt, bzw. erfolgen könnte.

Bei einem variablen Index müßte sowohl der Compiler entsprechend 
intelligent, als auch aus dem Code heraus der Wertebereich der Variablen 
exakt vorhersehbar sein. Das ist nicht immer grundsätzlich gegeben.

Bei einer einfachen for-Schleife wäre zum Beispiel machbar. Stattdessen 
kann man den Zugriff an sich in eine Funktion einbetten die zur Laufzeit 
prüft ob der Zugriff korrekt erfolgt. Das kostet natürlich Ressourcen, 
erfordert aber keine so speziellen Vorbedingungen.

von Sebastian M. (cyberseb) (Gast)


Lesenswert?

Hallo zusammen,

@Falk: Klar kann man das auch mit einer LED machen. Aber hier müsste ich 
ggf. den Code anpassen, was ich vermeiden möchte. Das mit dem Oszi 
sollte schon klappen, es ist ja ein digitales Speicheroszi und für eine 
One-Shot-Messung sollte es taugen. Nur um zu sehen, dass das Programm 
irgendetwas tut.

Mir ist es klar, dass es "pikant" ist, um Euren Rat zu fragen, ohne den 
Quellcode zeigen zu wollen. Wenn ich gewusst hätte, dass wir derart tief 
einsteigen, hätte ich vermutlich den Thread gar nicht erst gestartet. 
Ich war halt der Hoffnung, dass das vielleicht auf dieses Phenomen 
schonmal gestoßen ist. Ich bin jedoch guter Dinge, dass noch etwas 
Interessantes für das Forum herauskommt.

@Carsten: Das Display ist das "DISPLAYTECH 126C" von Reichelt 
(http://www.reichelt.de/LCD-162C-LED/3/index.html?&ACTION=3&LA=446&ARTICLE=31653&artnr=LCD+162C+LED&SEARCH=displaytech+162c).

An das Display wird nur geschrieben, nichts wird gelesen. Also dass mein 
Programm auf irgendeine Antwort vom LCD wartet ist damit ausgeschlossen. 
Auch ein Delay vor dem Initialisieren des Displays brachte nichts.

Abgesehen vom Display macht mein Programm im Fehlerfall sonst auch 
nichts. Normalerweise müssten die PWM-Timer (Sinus-Erzeugung) 
anspringen. Tun sie aber nicht. Das Programm startet m.E. gar nicht.

Mit dem Neustart hast Du Recht, es ist kein Reset. Um es noch mal klar 
dazurstellen, das ist der Ablauf:

1. Schaltung läuft bereits (mit oder ohne Fehler, je nachdem, was vorher 
passiert ist)
2. Flashen mit AVR-ISP, incl. Reset durch den AVR-ISP
3. Programm startet korrekt => Kein Fehler
4. Schaltung ausschalten
5. Schaltung einschalten (Neustart) => Fehler, Programm startet nicht

Dabei können 2. und 3. bzw. 4. und 5. beliebig wiederholt werden; das 
Verhalten ist reproduzierbar auf einem 2. Gerät.

Der Grundaufbau des Programms in main() ist dabei so:

1. LCD initialisieren
2. Willkommensnachricht anzeigen
3. Timer konfigurieren und starten (Sinus-Erzeugung mit PWM, 1/10
Millisekunden-Zeitmessung)
4. ADC initialisieren (optischer Sensor, Strommessung)
5. Betriebsparameter aus dem "virtuellen" EEPROM (für Wear-Leveling 
geshiftet) auslesen
6. Sinus-Amplitde hochfahren
7. Hauptschleife für "Hauptmenü", in der ggf. der Benutzer Funktionen 
mit umfangreicherer Programmlogik startet, sowie "nicht 
echtzeitkritische" Routineaufgaben (Stromüberwachung)

Über "1" kommt das Programm im Fehlerfall wohl nicht hinaus, sonst würde 
ich einen leeren Bildschirm sehen und keinen schwarzen Balken.

Selbst wenn ich irgendwo Mist mit Arrays verzapft habe (z.B. über deren 
Grenzen hinausschreibe), kann das vor "7" gar nicht passieren (ich kann 
aber noch nicht ausschließen, dass ich bereits ab "3" einen Fehler drin 
habe). Und bei meinem oben beschrieben Ablauf wurden niemals Funktionen 
durch den User (also mich) aufgerufen.

Lösche ich dagegen Programmteile aus der Hauptschleife (6) heraus (die 
ich während der Tests nicht benötige oder gar aufrufe), startet das 
Programm jedoch einfwandfrei!

Ich werde an dem Code morgen weiterdebuggen, und will dabei wie folgt 
vorgehen:

1. Mit dem Oszi die LCD-Datenleitungen überprüfen, ob irgendetwas im 
Fehlerfall gesendet wird.

2. (Quick&Dirty): Schauen, ob das Umsortieren der globalen 
Variablendeklarationen einen Einfluss auf das Verhalten hat.

4. Schauen, ob ich die Schaltung resetten kann, z.B. über den AVR-ISP 
oder einen Schalter (um den Neustart zu umgehen).

3. Alle Array-Operationen prüfen, ggf. noch eine explizite Routine in 
z.B. die For-Schleifen einbauen, die die Grenzen überwacht und einen 
Fehler über das Display meldet. Könnte tricky werden, weil ich hier den 
Code verändere ...

Viele Grüße
Sebastian

von Tom (Gast)


Lesenswert?

Schaltung manuell resetten -> gemeint ist, den Reset-Pin im laufenden 
Betrieb kurz manuell auf Masse zu legen

von Tom (Gast)


Lesenswert?

Und bedenke bitte, dass du mit dem Code oben nur den aktuell freien RAM 
rausbekommst. In einem Unterprogramm kann viel weniger zur Verfügung 
stehen. Besser ist der Minimum-Code von hier:
http://rn-wissen.de/wiki/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc#Dynamischer_RAM-Verbrauch

von Falk B. (falk)


Lesenswert?

@Sebastian M. (cyberseb) (Gast)

>ggf. den Code anpassen, was ich vermeiden möchte. Das mit dem Oszi
>sollte schon klappen, es ist ja ein digitales Speicheroszi und für eine
>One-Shot-Messung sollte es taugen.

Warum jammmerst du dann rum?

"Als nächstes werde ich mal mit dem Oszi schauen, ob das Programm im
Fehlerfall überhaupt irgendetwas macht. Könnte mit meinem alten Hameg
205 schwierig werden."

>anspringen. Tun sie aber nicht. Das Programm startet m.E. gar nicht.

Merkwürdig.

>1. Schaltung läuft bereits (mit oder ohne Fehler, je nachdem, was vorher
>passiert ist)
>2. Flashen mit AVR-ISP, incl. Reset durch den AVR-ISP
>3. Programm startet korrekt => Kein Fehler
>4. Schaltung ausschalten
>5. Schaltung einschalten (Neustart) => Fehler, Programm startet nicht

Das ist schon mal eine wichtige Aussage. Klingt nach wie vor nach einem 
Initialisierungsproblem. Vielleicht hängt ein wichtiger Eingangspin in 
der Luft, weil ein Pull-Up Widerstand fehlt.

>Der Grundaufbau des Programms in main() ist dabei so:

Spar dir die Lyrik, zeig den Quelltext sowie den Schaltplan!

>Über "1" kommt das Programm im Fehlerfall wohl nicht hinaus, sonst würde
>ich einen leeren Bildschirm sehen und keinen schwarzen Balken.

Also ist schon mal was Grundlegendes falsch. Möglicherweise eine 
IO-Initialisierung. Für ein bisschen LCD-Ansteuerung reichen ein paar 
Bytes RAM meistens aus, wenn man nicht mit printf() & Co arbeitet.

>Lösche ich dagegen Programmteile aus der Hauptschleife (6) heraus (die
>ich während der Tests nicht benötige oder gar aufrufe), startet das
>Programm jedoch einfwandfrei!

Hmmm.

>1. Mit dem Oszi die LCD-Datenleitungen überprüfen, ob irgendetwas im
>Fehlerfall gesendet wird.

Sinnvoll.

>2. (Quick&Dirty): Schauen, ob das Umsortieren der globalen
>Variablendeklarationen einen Einfluss auf das Verhalten hat.

Wenig sinnvoll.

>4. Schauen, ob ich die Schaltung resetten kann, z.B. über den AVR-ISP
>oder einen Schalter (um den Neustart zu umgehen).

?

>3. Alle Array-Operationen prüfen, ggf. noch eine explizite Routine in
>z.B. die For-Schleifen einbauen, die die Grenzen überwacht und einen
>Fehler über das Display meldet. Könnte tricky werden, weil ich hier den
>Code verändere ...

Wenig sinnvoll. Wenn der Fehler reproduzierbar ist, muss man die Stelle 
finden, wo das Programm GENAU hängen bleibt!

von Tom (Gast)


Lesenswert?

Wenn du nicht magst, reicht eventuell auch schon der komplette Code 
zumindest bis einschließlich des LCD-Inits.
Vielleicht "initialisiert" du ja manche Register mit &= oder |= oder so. 
Setzt also gewisse Anfangszustände voraus.

von Sebastian M. (cyberseb) (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Tom & Falk,

danke für Eure Hilfe!

Vielleicht mache ich wirklich Mist mit dem Initialisieren des LCDs. Ich 
muss das morgen mal in Ruhe durchgehen und testen. Ich werde berichten - 
und mich (vermutlich) schämen ... :-/

Wobei mir immer noch nicht wirklich klar ist, wie ein ungenutzter Code 
(weiter unten in main, der auch nichts an den Ports macht) Einfluss auf 
die LCD-Initialisierung haben kann, je nachdem, ob er auskommentiert 
ist, oder nicht. Und die Rolle des AVR-ISPs ... Ich hoffe, das wird noch 
interessant.

Schaltplan hängt an! (Der AVR-ISP könnte da ja Einfluss darauf haben, 
wenn sich das LCD mit dem AVR-ISP Leitungen teilen würde. Tut er aber 
nicht ...)

Gruß, Sebastian

von Tom (Gast)


Lesenswert?

Hmmmm... Abblockkondensatoren?

von Sebastian M. (cyberseb) (Gast)


Lesenswert?

@Tom: Am freien RAM sollte es nicht liegen. Ich habe den mit der o.g. 
Routine intervallmäßig per Timer in verschiedenen Programmteilen auf dem 
LCD ausgegeben.

Das waren bei dem alten (fehlerhaften) Code um die 500 Byte frei. Tiefe 
Rekursionen habe ich ebenfalls nicht.

Ich werde das aber noch weiter im Auge behalten, erstmal schau ich mir 
die LCD-Initialisierung an ...

Gruß, Sebastian

von Sebastian M. (cyberseb) (Gast)


Lesenswert?

Tom schrieb:
> Hmmmm... Abblockkondensatoren?

C5 ist auf dem PCB direkt neben dem AVR ...

von Tom (Gast)


Lesenswert?

Neben VCC oder AVCC? xD Fällt dir was auf?

von M. K. (sylaina)


Lesenswert?

Tom schrieb:
> Neben VCC oder AVCC? xD Fällt dir was auf?

Es müsste nur noch jemand einen passenden Schluss erklären können warum 
dann das Programm läuft wie gewünscht, wenn der nicht benutzte Code 
auskommentiert wird. Für mich ist das irgendwie nicht wirklich 
schlüssig.

von Sebastian M. (cyberseb) (Gast)


Lesenswert?

Hallo Tom,

bei mir hängen VCC, AVCC und AREF an +5V, die über 100n gegen Masse 
gehen.

Nach https://www.mikrocontroller.net/articles/Datei:Mega8_Tutorial.png 
sollte AREF jedoch über einen Kondensator auf Masse gehen.

Ich dachte, ich verwende die +5V als Referenzspannung, darum hängt der 
an +5V.

Scheinbar ist das doch komplizierter, als ich dachte. Ich werde wohl den 
Thread hier durcharbeiten müssen: 
Beitrag "AREF = AVCC ????" ...

Gruß, Sebastian

von Tom (Gast)


Lesenswert?

Mit "versauter" Versorgung ist alles möglich. Da reicht es schon, wenn 
eine Flash-Zelle falsch gelesen wird, weil die Spannung gerade einen 
Einbruch hat. Die Zelle ist in der einen Code-Variante vielleicht in 
Verwendung und bei der anderen nicht.
Löte mal SMD-Kerkos direkt an die Pins des Käfers dran. Zwischen VCC und 
GND sowie zwischen AVCC und GND.

von Tom (Gast)


Lesenswert?

Wie du AREF beschaltest, hängt davon ab, wie du es benutzen willst! Wenn 
interne Referenz -> Nur Kerko nach Masse.
Wenn eine externe Spannung als Referenz, hängst du eben diese dran (und 
Kerko nach Masse).
Was du machen willst, das weißt nur du. Deinen Code kennen wir ja nicht.

Ultrawichtig ist aber, dass du jeweils VCC und AVCC je einen Kerko 
spendierst!! Und zwar direkt am Chip, möglichst wenig Abstand.

von Sebastian M. (cyberseb) (Gast)


Lesenswert?

M. K. schrieb:
> Es müsste nur noch jemand einen passenden Schluss erklären können warum
> dann das Programm läuft wie gewünscht, wenn der nicht benutzte Code
> auskommentiert wird. Für mich ist das irgendwie nicht wirklich
> schlüssig.

Geht mir genau so.

Ich habe tatsächlich auskommentierte "defines" in meiner LCD.h gefunden:
1
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
2
...
3
#define  LCD_D4    SBIT( PORTD, 0 )
4
#define  LCD_DDR_D4  SBIT( DDRD, 0 )
5
#define  LCD_D5    SBIT( PORTD, 1 )
6
#define  LCD_DDR_D5  SBIT( DDRD, 1 )
7
#define  LCD_D6    SBIT( PORTD, 2 )
8
#define  LCD_DDR_D6  SBIT( DDRD, 2 )
9
#define  LCD_D7    SBIT( PORTD, 3 )
10
#define  LCD_DDR_D7  SBIT( DDRD, 3 )
11
#define  LCD_RS    SBIT( PORTB, 0 )  
12
#define  LCD_DDR_RS  SBIT( DDRB, 0 )
13
#define  LCD_E0    SBIT( PORTB, 1 )  
14
#define  LCD_DDR_E0  SBIT( DDRB, 1 )

und dann in LCD.c wird das dann direkt verwendet:
1
void lcd_init(void) {
2
3
LCD_DDR_D4 = 1;
4
LCD_DDR_D5 = 1;
5
...

Zwar werden die Ports direkts in meiner main.c als Ausgänge gesetzt 
(nicht aber sämtliche o.g. platzhalter wie LCD_DDR_D4). Mir ist nicht 
klar, warum das überhaupt funktioniert. WAS setzt er auf "1", z.B. bei

[c]LCD_DDR_D4 = 1;[c]

?

Irgendwas anderes im RAM? Das könnte evtl. das beschriebene Problem 
auslösen. Dann dürfte das LCD m.E. aber überhaupt nicht funktionieren 
und es wundert mich auch, warum der Compiler nicht meckert (auch nicht 
nach einem "make clean"). Woher nimmt der also diese Definitionen?

Ich muss das morgen mal an meiner Schaltung ausprobieren.

Wow, was da alles für Probleme zum Vorschein kommen. ICH DANKE EUCH!!!

@Tom: Danke für den Hinweis auf den extra Kondensator! Das werde ich 
noch ändern. Auch die Erklärungen hier: 
https://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC#Referenzspannung_AREF 
sind nützlich - z.B. sollte ich für die gewollte 5V Referenzspannung 
einfach die interne nehmen.

Gruß, Sebastian

von Marc V. (Firma: Vescomp) (logarithmus)


Angehängte Dateien:

Lesenswert?

Sebastian M. (cyberseb) schrieb:
> Scheinbar ist das doch komplizierter, als ich dachte. Ich werde wohl den
> Thread hier durcharbeiten müssen:
> Beitrag "AREF = AVCC ????" ...

 Bevor du dich in sinnlosen Versuchen verlierst...
 Stellen wir mal fest, was überhaupt passiert:

 A) Nach flashen läuft alles.
 B) Nach Reset oder Stromabschalten aber nicht mehr.
 C) In der Zwischenzeit macht er keine Probleme.
 Richtig so ?

 Wenn ja, dann überlege mal was sich zwischen Flashen und Reset
 verändert hat ?
 Flash kann sich nicht verändern und I/O Register werden auch nach
 Reset auf Initialwerte gesetzt.
 Bleibt nur - RICHTIG - RAM.

 Beim LCD-Init wird nichts gelesen, stimmt das ?
 Da es nach Flashen richtig startet, aber nach Reset nicht mehr, sind
 nur die Variablen interessant, die beim Initialisieren gebraucht
 werden.
 Sind wir uns soweit einig ?

 Wenn ja, dann setze alle Variablen, die beim Init gebraucht werden
 ganz vorne (oder ganz hinten, egal) und probiere es mal so.

 Anbei ein Excel mit Werten nach ISP-Flashen und flashen mit Boot-
 loader. Was interessant ist - bestimmte Bereiche im RAM behalten
 immer die gleichen Werte - sind zwar von uC zu uC verschieden, aber
 ab Adresse 269 z.B. behalten die immer den gleichen Wert.

 P.S.
 Es sind RAM-Adressen, nicht physikalische Adressen.

: Bearbeitet durch User
von Sebastian M. (cyberseb) (Gast)


Lesenswert?

Hallo zusammen,

vergesst das, was ich über die Defines geschrieben habe. Die sind 
natürlich nicht auskommentiert, sondern werden mit einem "#" 
eingeleitet. Ouch!

Marc, Deine Annahmen sind richtig. Danke für das interessante Dokument!

Marc V. schrieb:
>  Wenn ja, dann setze alle Variablen, die beim Init gebraucht werden
>  ganz vorne (oder ganz hinten, egal) und probiere es mal so.
>
>  Anbei ein Excel mit Werten nach ISP-Flashen und flashen mit Boot-
>  loader. Was interessant ist - bestimmte Bereiche im RAM behalten
>  immer die gleichen Werte - sind zwar von uC zu uC verschieden, aber
>  ab Adresse 269 z.B. behalten die immer den gleichen Wert.

Ich habe aber noch Probleme, das zu verstehen:

Was meinst Du mit "setzen"? Also den Variablen einen Wert zuweisen? Das 
mache ich doch. Sollten die entsprechenden Speicherstellen bei einem 
erneuten Start (egal ob mit oder ohne ISP) nicht automatisch dazu 
führen, dass diese mit den gewünschten Variablenwerten befüllt werden?

Oder meinst Du mit "setzen" die Position im Code? Was meinst Du mit 
"hinten"? D.h., ich sollte über die Position im Code erzwingen, dass die 
Variblen im RAM vor Adresse 269 landen?

Heißt das, dass alles nach einem ISP-Flash nach dieser Position im RAM 
erhalten bleibt? Was passiert dann aber mit dem Code, mit dem ich die 
Variablen setze? Wird der ignoriert?

Gruß, Sebastian

von Tom (Gast)


Lesenswert?

Du solltest deine Register beim Start ordentlich initialisieren. Keine 
Bits gezielt löschen/setzen, sondern einfach einen definierten Wert 
reinschreiben. Du weißt ja nicht, was vorher drin war.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sebastian M. (cyberseb) schrieb:
> Oder meinst Du mit "setzen" die Position im Code? Was meinst Du mit

 Ja, die Position war gemeint. Compiler wird wahrscheinlich die Adressen
 im RAM entsprechend der Reihenfolge der Deklarationen zuweisen.
 Falls du Arrays hast, deklariere ein paar Dummy-Variablen dahinter,
 deklariere Pointer als volatile und integer etc.

> "hinten"? D.h., ich sollte über die Position im Code erzwingen, dass die
> Variblen im RAM vor Adresse 269 landen?

 Nicht unbedingt, ich wollte nur sagen, dass die RAM-Inhalte bei
 bestimmten Speicherzellen bzw. Adressen nicht ganz zufällig sind, nach
 flashen einen bestimmten Wert haben, aber nach Ausschalten und Reset
 wiederum einen ganz anderen.

 Ich arbeite selten mit C, bin mir also nicht sicher wie der Compiler
 das genau macht, aber ich könnte mir vorstellen, dass beim include
 schon RAM reserviert wird, falls du - wenn auch später - irgendwelche
 Routinen aus diese library benutzst.
 Wie gesagt, C ist nicht meine Stärke, wird es auch nie werden, ist
 also nur eine Vermutung. Auf jeden Fall sollte der Compiler das
 merken, ist also unwahrscheinlich, aber Arraygrenzen (Laufzeit) prüft
 er ganz bestimmt nicht.

: Bearbeitet durch User
von Sebastian M. (cyberseb) (Gast)


Lesenswert?

Tom: Wird morgen gemacht. Bei einigen Register setzt ich tatsächlich nur 
die Bits, die ich benötigte. Auf solche möglichen Seiteneffekte (wenn 
man einzelne Bits nicht explizit setzt) wäre ich nicht gekommen.

Marc: Danke, jetzt ist es mir klar, was Du gemeint hast. Ich werde als 
nächstes den Code durchgehen, vermutlich laufe ich irgendwo über eine 
Array-Grenze hinweg. Das könnte solche Effekte, wie Du sie beschrieben 
hast, zum Fehlerfall führen lassen.

Herzlichen Dank!

Ich werde Euch auf dem Laufenden halten.

Gruß, Sebastian

von neuer PIC Freund (Gast)


Lesenswert?

Ich vermisse im Schaltplan einige Verbindungspunkte. Z.b. bei C3 und C5. 
Sind die wirklich angeschlossen, oder halt nur auf dem Board vorhanden?

von Sebastian M. (cyberseb) (Gast)


Lesenswert?

Das müsste alles richtig verbunden sein. Ich glaube eher, da sind zu 
viele "überflüssige" grüne Punkte drin, weil ich mir beim Erstellen des 
Plans auch nicht ganz sicher war, wie KiCad das verarbeitet. Beim 
Erstellen des PCBs bzw. beim "Check" wären die aber aufgeflogen. Ja, den 
Plan muss ich auch noch schöner machen, bevor das Ding mal fertig wird 
... :-)

Danke für den Hinweis!

Gruß, Sebastian

von Bernd K. (prof7bit)


Lesenswert?

Bau mal ne Verzögerungsschleife ein von ein paar dutzend Millisekunden, 
ganz am Anfang bevor Du anfängst das Display zu initialisieren.

Beim Aus- und Einschalten vorher den ISP-Stecker abziehen sonst spuckt 
Dir der AVRISP möglicherweise in die Suppe, dem wird nämlich schwindelig 
wenn das Gerät eingeschaltet wird während er dransteckt und er übergibt 
sich dann über die Reset-Leitung.

von Bernd K. (prof7bit)


Lesenswert?

Marc V. schrieb:
> Ich arbeite selten mit C, bin mir also nicht sicher wie der Compiler
>  das genau macht, aber

Warum ergehst Du Dich dann in wilden Spekulationen und Behauptungen 
darüber?

von Carsten R. (kaffeetante)


Lesenswert?

So, nun bin ich wieder zuhause. Wegen dem "Strom aus, Pause, Strom an" 
vs reset über Resetpin hatte ich vergessen zu sagen.

Pack gleich in in die Startroutine zuallererst, also so das wirklich 
absolut nichts anderes vorher ausgeführt wird und werden kann, ein Delay 
bzw. eine Warteschleife die den Start um ein paar Hundert Millisekunden 
verzögert, so daß sichergestellt ist daß die Spannung sich stabilisiert 
hat und zusätzlich noch etwas mehr Zeit verstrichen ist für die von den 
Chips geforderte Wartezeit !nach! anliegen einer stabilen Spannung.

Normalerweise braucht das nicht so lange sein, aber wir hkennen die 
Qualität deiner Spannungsversorgung nicht.

Nachtrag:

Bernd war schneller mit dem Absenden. Ich würde glatt ein Bier auf die 
Warteschleife verwetten. :D

: Bearbeitet durch User
von Carsten R. (kaffeetante)


Lesenswert?

Im Datenblatt des Displays steht:

"Wait for more than 15ms after VDD rises to 4.5V"

Hast du das berücksichtigt?

von Sebastian M. (cyberseb) (Gast)


Lesenswert?

Hallo zusammen,

danke für den Hinweis - ich hatte weiter oben aber schon geschrieben, 
dass ich das auch schon probiert hatte:

Sebastian M. (cyberseb) schrieb:
> An das Display wird nur geschrieben, nichts wird gelesen. Also dass mein
> Programm auf irgendeine Antwort vom LCD wartet ist damit ausgeschlossen.
> Auch ein Delay vor dem Initialisieren des Displays brachte nichts.

Naja, ich kann noch mal mit anderen Werten experimentieren.

Mein Buchgefühl sagt mir aber, dass es nicht am LCD liegt. Da wird ja 
nur geschrieben und nicht gewartet. D.h, der AVR würde "drüberumpeln" 
und mit dem Programm weitermachen, z.B. die PWM aktivieren. Macht er 
aber nicht.

Carsten, das mit dem Delay schaue ich morgen an. Aber ich glaube nicht, 
dass es daran liegt. Dafür ist das ganze Verhalten zu zufällig, und das 
gefällt mir absolut gar nicht ... Vor allem, dass sich das Vorhandensein 
von ungenutztem Programmcode irgendwie auswirkt! :-/

So wild finde ich Bernds Spekulationen gar nicht. Ich kann mir gut 
vorstellen, dass ich über eine Arraygrenze hinausschreibe, und die von 
Bernd beschrieben Effekte eine Auswirkung auf den Fehler haben. Fehlt 
der unbenutzte Code, werden vielleicht die Variablendeklarationen vom 
Compiler anders sortiert und der Fehler fällt nicht auf.

Inzwischen habe ich alle for-Schleifen und Array-Operationen überflogen, 
sieht (leider!) gut aus. Relevant sind sicher nur die, die auch während 
des Tests liefen. Das sind eigentlich nur die für das Abfahren der 
Sinus-Tabelle und die zum Anpassung der Spannung bzw. Soft-Start (durch 
Hochskalieren der Werte). Die erste ist etwas komplizierter, die zweite 
ist wohl OK. Ich werde das morgen in Ruhe durchgehen und debuggen.

Seit den Updates (Compiler, Eclipse-AVR-Plugin) ist der Fehler ja 
verschwunden und bleibt das hoffentlich auch. Vielleicht war das 
wirklich ein Bug in der Toolchain (glaube ich aber nicht). Ich will den 
Fehler aber trotzdem finden (alte Toolchain kann ich auch noch 
verwenden).

Viele Grüße, Sebastian

von Sebastian M. (cyberseb) (Gast)


Lesenswert?

Ich meinte natürlich "Marcs Spekulationen", sorry!

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bernd K. schrieb:
> Marc V. schrieb:
>> Ich arbeite selten mit C, bin mir also nicht sicher wie der Compiler
>>  das genau macht, aber
>
> Warum ergehst Du Dich dann in wilden Spekulationen und Behauptungen
> darüber?

 Erstens, es sind keine wilden Behauptungen und Spekulationen, sondern
 logisches denken - was bei dir ja scheinbar fehlt.
 Zweitens, weil es bestimmte Regeln gibt, die ein Compiler ganz einfach
 befolgen muss, egal ob Pascal oder C.
 Drittens, du als attestiertes Genie weisst natürlich bis ins kleinste
 Detail wie der Compiler das macht ?

 Schweig still, wenn du nichts gescheites zu sagen hast, ausser zu
 meckern.

: Bearbeitet durch User
von Bad U. (bad_urban)


Lesenswert?

Marc V. schrieb:
> Flash kann sich nicht verändern und I/O Register werden auch nach
>  Reset auf Initialwerte gesetzt.
>  Bleibt nur - RICHTIG - RAM.

Oder interne Register der Peripherie. Möglicherweise gibt es beim AVR 
auch Register die sich bei POR anders verhalten als bei einem manuellen 
Reset über den Reset-Pin. Ich arbeite zwar mit PICs, aber da ist das so. 
Das Datenblatt unterscheidet bei Initialwerten zwischen POR-BOR und 
manuellem, WDT oder Softreset. Und bei einigen Registern macht das 
Unterschiede. Vielleicht gibts sowas ja auch beim AVR.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bad U. schrieb:
> Oder interne Register der Peripherie. Möglicherweise gibt es beim AVR
> auch Register die sich bei POR anders verhalten als bei einem manuellen
> Reset über den Reset-Pin. Ich arbeite zwar mit PICs, aber da ist das so.

 Nö.
 Beim AVR macht es keinen Unterschied, es gibt 4 Arten von Reset,
 bei allen ist das Verhalten nach dem Reset genau dasselbe.
 Funktionert sogar ohne Clock.

: Bearbeitet durch User
von Bad U. (bad_urban)


Lesenswert?

Ok. Dann kann man das schonmal als Fehlerursache ausschließen :)
Ich wollte das auch nur mal in den Raum werfen, weil ich da auch schon 
drüber gestolpert war.

von Sebastian M. (cyberseb)


Lesenswert?

Hallo zusammen,

also, ich habe weiter debuggt und das sind meine Ergebnisse:

- Der Controller startet im Fehlerfall gar nicht (und "rumpelt" auch 
nicht über die LCD-Initialisierung drüber), denn die PWM wird nicht 
aktiviert.
- Schleifen und Array-Zugriffe sind OK, ich habe die Grenzen zur 
Laufzeit überwacht (Fehler wären auf dem LCD ausgegeben worden).
- Verschiedene Delays vor der Display-Initialisierung haben keinen 
Einfluss.

Und ich habe interessante neue Erkenntnisse, die wohl belegen dürften, 
dass dies kein Standardfehler ist!

Dazu habe ich mein Programm wie folgt abgeändert:

1
int main(void) {
2
3
   lcd_init(); // Befehl 1 
4
   screen_print("Hello World"); // Befehl 2 
5
   _delay_ms(10000);            // Befehl 3  
6
   
7
   screen_print_twoLines(("Begrüßungs"), 1, ("Text"), 2); // Befehl 4
8
9
   // Timer und alles andere initialisieren
10
   // Programm-Hauptschleife

Das Delay dient dazu, dass ich einen Reset bzw. Neustart des Programms 
machen kann, ohne dass der Code darunter zur Ausführung kommt. Außerdem 
wird der Code darunter nicht wegoptimiert und damit kleiner.

Auch hier lässt sich der Fehler wie oben beschrieben reproduzieren! Das 
Programm startet korrekt nach dem Flashen, nicht aber nach einem 
Neustart (Strom aus, Strom an). Bei dem Test wurde niemals Befehl 4 
ausgeführt, weil ich den Neustart immer während Befehl 3 ausgeführt 
habe.

Also dass mein Code nach Befehl 3 irgendetwas im RAM ändert, kann ich 
damit ausschließen, da er nie zur Ausführung kommt.

Interessant: Kommentiere ich jedoch Befehl 4 aus, tritt der Fehler nicht 
auf.

Ich kann mir absolut keinen Reim daraus machen, wie nicht ausgeführter 
Code einen Einfluss auf das Verhalten haben kann! Doch ein Compiler-Bug? 
:-(

Gruß, Sebastian

: Bearbeitet durch User
von Tom (Gast)


Lesenswert?

Evtl. mal den Simulator nehmen?

von Sebastian M. (cyberseb)


Lesenswert?

Tom, mir wird wohl nichts anderes übrigbleiben, wenn ich den Fehler 
finden werde. Ich hab mit dem Simulator noch nie etwas gemacht, aber ich 
werde mich einarbeiten.

Ach ja, um Fehler bei der Stromversorgung (Ripple durch Schaltregler, 
usw.) auszuschließen, habe ich folgendes Gemessen:

DC: 4,98V (Multimeter)
Ripple: ca. +/- 30mV (Soweit ich das mit dem Oszi beurteilen kann)

Sollte also passen ... Meh! :-(

Gruß, Sebastian

von Tom (Gast)


Lesenswert?

Ne, die Ripple, die den uC durcheinanderbringen, kannst du im 
Zweifelsfall gar nicht messen. Wie sieht es denn an der Kerkofront aus? 
Hast du da mal welche drangelötet (VCC-GND, AVCC-GND, AREF-GND)? Die 
sind wichtig. Also, angenommen, ich wäre dein Kunde. Dann würde ich da 
welche sehen wollen!

von Sebastian M. (cyberseb)


Lesenswert?

Das war gerade mein nächster Versuch ...

Brachte leider auch nichts. Allerdings sind das keine 
Keramikkondensatoren, sondern Wima MKS-02, 100nF. Müssen das unbedingt 
Keramikkondensatoren sein?

Die kommen aber auf jeden Falls ins finale Schaltungsdesign.

Als nächstes würde ich die Schaltung auf dem Breadboard nachbauen bzw. 
eine Minimalbeschaltung, um zu schauen, ob das Programm dann startet ...

Oder hey, ich probiere einen Arduino. Zumindest die PWM sollte ich 
messen können! :-)

Gruß, Sebastian

von blablablubb (Gast)


Lesenswert?

Sebastian M. schrieb:
> Also dass mein Code nach Befehl 3 irgendetwas im RAM ändert, kann ich
> damit ausschließen, da er nie zur Ausführung kommt.

Dem Compiler steht es durchaus frei Teile von 4 vor 3 zu machen, wenn 
das das Gesamtergebnis aus der Sicht des Compilers nicht beeinflusst.
Es ist also unzulässig anzunehmen, dass nichts von 4 ausgeführt wurde.

von Carsten R. (kaffeetante)


Lesenswert?

Woher weißt Du das die vierte Zeile nie zur Ausführung kommt? Wenn du es 
daraus schließt, daß der Text nicht erscheint, sollte man prüfen ob der 
Fehler nicht in der Routine selbst liegen könnte. Diesen Schluß würde 
ich daraus ziehen.

Sebastian M. schrieb:
> An ein
> (einfaches) Initialisierungsproblem glaube ich nicht - es hängt
> definitiv mit dem Speicher zusammen.
>
> Ob es geht, oder nicht, ist von diesen zwei Codezeilen abhängig. Und die
> sind mitten im Code, weit, weit weg von der Initialisierung:
>
>    screen_locate(1, 2);
>    screen_print("(Speed restored)");

Das ist ein Trugschluß. Initialisierungsproblem bedeutet nicht, daß das 
Problem zwangsläufig während der Initialisierung auftritt, sondern nur 
daß sie nicht korrekt durchgeführt wird. Das kann sofort zu Problemen 
führen, muß aber nicht. Initialisierung ist kein Selbstzweck, sondern 
dient der Vorbereitung, damit nachfolgende Operationen korrekt auf einer 
sauber definierten Basis durchgeführt werden. War die Initialisierung 
fehlerhaft, so kann der Fehler später bei den Funktionen auftreten die 
sich auf die Initialisierung stützen. Es muß auch nicht unbedingt diese 
Hardware sein, es kann natürlich auch eine nicht definierte 
Speicherstelle sein, welche je nach Startbedingung eventuell etwas 
anders aussieht.

Mit screen_print_p funktioniert es aber. Worin besteht der Unterschied 
der beiden Funktionen? Verwendet screen_print_p auch lcd_text oder 
lcd_data? Wie sieht lcd_data aus?

Sebastian M. schrieb:
> Den Code möchte ich nicht zeigen,

Dann können wir dir auch nicht helfen! Was nützen uns lustige 
Methodennamen und Codefitzelchen, wenn wir nicht wissen dürfen was sie 
bedeuten? Wir können keinen Code debuggen den wir nicht sehen dürfen.

von Sebastian M. (cyberseb)


Lesenswert?

Arduino Duemilanove (China-Clone) mit Quarz (kein Keramik-Resonator), 
gleicher AVR-Typ:

Gleiches Verhalten (fast).

Ich habe zwar kein LCD dran, aber die PWM startet brav nach einem Flash 
(über den AVR-ISP). Nach einem Reset über den Reset-Button startet sie 
nicht.

Nehme ich dem Arduino kurz seine 5V (USB-Stecker ziehen), so:
- startet das Programm, wenn der AVR-ISP angeschlossen ist
- startet das Programm nicht, wenn der AVR-ISP nicht angeschlossen ist.

Im ersten fall könnte das mit dem zusätzlichen Reset durch den AVR-ISP 
zusammenhängen (der resettet auch nochmal, wenn die Schaltung wieder 
Strom kriegt). Wildes Rumdrücken auf dem Reset-Taster hilft auch nichts. 
:-)

Seeeehr seltsam ...

Gruß, Sebastian

von blablablubb (Gast)


Lesenswert?

Sebastian M. schrieb:
> Wildes Rumdrücken auf dem Reset-Taster hilft auch nichts.

Was macht der Reset-Taster? RESET auf GND ziehen? Mehr macht der ISP 
auch nicht.

von Sebastian M. (cyberseb)


Angehängte Dateien:

Lesenswert?

blablablubb schrieb:
> Dem Compiler steht es durchaus frei Teile von 4 vor 3 zu machen, wenn
> das das Gesamtergebnis aus der Sicht des Compilers nicht beeinflusst.
> Es ist also unzulässig anzunehmen, dass nichts von 4 ausgeführt wurde.

Interessante Überlegungen - könnte durchaus wohl sein ...

Carsten R. schrieb:
> Woher weißt Du das die vierte Zeile nie zur Ausführung kommt? Wenn du es
> daraus schließt, daß der Text nicht erscheint,

Weil ich den Controller innerhalb des 10-Sekunden-Delays neu starte ...

Carsten R. schrieb:
> Mit screen_print_p funktioniert es aber. Worin besteht der Unterschied
> der beiden Funktionen? Verwendet screen_print_p auch lcd_text oder
> lcd_data? Wie sieht lcd_data aus?

Das verwendet den Program-Space (PROGMEM). Kommt aber in der 
fehlerhaften Version zuletzt gar nicht mehr zum Einsatz.

Carsten R. schrieb:
> Dann können wir dir auch nicht helfen! Was nützen uns lustige
> Methodennamen und Codefitzelchen, wenn wir nicht wissen dürfen was sie
> bedeuten? Wir können keinen Code debuggen den wir nicht sehen dürfen.

Klar ... Aber um Deine Überlegungen mit der Initialisierung weiterführen 
zu können, habe ich den relevanten Code angehängt - ich hoffe, der ist 
ausreichend. Ich würde mich freuen, wenn Du drüberschauen könntest.

Viele Grüße
Sebastian

von Tom (Gast)


Lesenswert?

Das heißt, das Erste, das man messen könnte, wäre ein High-Pegel auf D4 
und D5, gefolgt von einem kurzen Impuls auf E0?

von Fritz G. (fritzg)


Lesenswert?

Hast du dir das Quarz Signal angesehen, vielleicht schwingt der nicht 
sauber?

von blablablubb (Gast)


Lesenswert?

Dieser Code compiliert mit Sicherheit nicht. Bitte Code posten, der das 
Problem aufzeigt und funktioniert.

Aber ansonsten:
Warum dieser Quatsch mit der Bitstruktur? Einfach Bitoperatoren, die der 
Compiler vernünftig optimieren kann, wäre wohl zu einfach gewesen.

Das include guard #endif zu #ifndef lcd_drv_h steht mitten im Header. 
Die Hälfte des Headers ist also nicht geschützt.

const wegcasten ist keine gute Idee. Das kann zu undefiniertem Verhalten 
führen. Mache ein const u8* bei lcd_text.

von Tom (Gast)


Lesenswert?

Der Code setzt übrigens auch die Register nicht auf definierte Werte, 
sondern popelt nur bitmäßig daran herum. Das ist kein sauberer Init.

von Tom (Gast)


Lesenswert?

Deine Nibble-Funktion löscht auch Bits vor dem Setzen kurz. Wenn D4 z.B. 
high war, wird es, wenn es nach dem Aufruf wieder high sein soll, kurz 
auf low getoggelt. Eigentlich kein Problem, aber total unschön.

von Sebastian M. (cyberseb)


Lesenswert?

blablablubb & Tom, ihr seid super!

Fragt mich nicht, aus welchen Codeschnipsen ich die LCD-Routinen vor 
Jahren zusammengebastelt habe ... Die hatten sich bisher bewährt, 
jahrelang funktioniert und ich habe sie nie hinterfragt.

Die Routinen fliegen raus und werden von Grund auf neu geschrieben.


Tom schrieb:
> Das heißt, das Erste, das man messen könnte, wäre ein High-Pegel auf D4
> und D5, gefolgt von einem kurzen Impuls auf E0?

Die sind schon von Beginn auf High und bleiben dann dort (im Fehlerfall)

Fritz G. schrieb:
> Hast du dir das Quarz Signal angesehen, vielleicht schwingt der nicht
> sauber?

Sollte passen, nachdem der Fehler auf einem Arduino auch auftritt ...

Gruß, Sebastian

von Tom (Gast)


Lesenswert?

Du könntest dir auch die ersten Zeilen des Assemblercodes angucken bzw. 
mit dem Ergebnis des neuen avr-gcc vergleichen.

von Sebastian M. (cyberseb)


Lesenswert?

Also, die LCD-Rotinen sind ausgetauscht. Ich habe im Prinzip die hier 
verwendet: 
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung#Die_LCD_Routinen 
und entsprechend angepasst und erweitert.

Das Problem besteht weiterhin.

Ich glaube auch langsam, dass wir an einem Punkt angekommen sind, an dem 
Ihr mir ohne den Quellcode nicht helfen könnt. Wenn ich die Ursache 
nicht finde, kann ich nur darauf hoffen, dass der neure 
speicherplatzoptimierte Code (mit dem neueren GCC kompiliert) 
einwandfrei läuft. Bis jetzt tut er es ...

Ansonsten habe ich noch die Variablen, die in den Interrupt-Routinen 
verwendet werden, überprüft. Da waren tatsächlich zwei noch nicht auf 
volatile gesetzt. Das brachte aber auch nichts.

Tom, das ist eine gute Idee. Ich schaue mal, ob ich den kompletten 
Build-Prozess einmal mit dem alten und einmal mit dem neuen Compiler 
GLEICH (d.h., ohne andere Compiler-Optionen, was über Eclipse gar nicht 
so einfach geht) durchziehen kann.

Wenn ich auf etwas stoße, lasse ich es Euch wissen.

Auf jeden Fall: HERZLICH DANK - ich hätte nicht damit gerechnet, dass 
Ihr so hilfsbereit bei einem closed-source Projekt seid. Vielleicht kann 
ich der Community ja doch noch etwas zurückgeben, falls ich die Ursache 
finde.

Viele Grüße
Sebastian

von Tom (Gast)


Lesenswert?

Ja, oder du nimmst nur den alten Compiler und entfernst dann die "nicht 
genutzten" Programmteile, sodass die Initialisierung klappt (wie du es 
mal beschrieben hast) und nimmst dann dieses Kompilat für den Vergleich. 
Das Entscheidende müsste ja gleich an Anfang stehen...

von Sebastian M. (cyberseb)


Angehängte Dateien:

Lesenswert?

Tom, Du bist genial! Danke! :-)

So hab ichs gemacht. Und tatsächlich gibt es am Programmanfang einen 
Unterschied, je nachdem ob weiter unten im Code etwas auskommentiert ist 
(was wie gesagt nie ausgeführt wird).

Und zwar macht er im fehlerbehafteten Code ein "push r0" bevor es 
losgeht.

Im Diff-Screenshot links hellblau markiert.

Ich verstehe das noch nicht - ich habe ehrlich gesagt noch nie Assembler 
programmiert. Ich bleibe aber dran und werde mal schauen, was die 
neueren Compiler mit dem Code anstellen.

Gruß, Sebastian

von Sebastian M. (cyberseb)


Angehängte Dateien:

Lesenswert?

Der neue Compiler macht dagegen einen viel kürzeren ASM-Code, bevor es 
überhaupt losgeht ...

von Carsten R. (kaffeetante)


Lesenswert?

Sebastian M. schrieb:
> Carsten R. schrieb:
>> Woher weißt Du das die vierte Zeile nie zur Ausführung kommt? Wenn du es
>> daraus schließt, daß der Text nicht erscheint,
>
> Weil ich den Controller innerhalb des 10-Sekunden-Delays neu starte ...

Ich habe eine begrenzte Ahnung was du machst. Es wäre hilfreich wenn du 
das was du beschreibst noch einmal kontrollierst ob es für jemanden 
nachvollziehbar ist, der nicht sieht was du tust. Du nimmst zuviel als 
gegeben an.

Entweder er kommt in beiden Fällen zum Delay und du startest vor Zeile 4 
manuell neu. Das bedeutet es Funktioniert in beiden Fällen, Reset durch 
Programmer und Manuelle Stromunterbrechung. Dann kannst du mangels 
unterschied aber nicht diesen Schluß ziehen.

Sebastian M. schrieb:
> Auch hier lässt sich der Fehler wie oben beschrieben reproduzieren!

Oder das Teil kommt tatsächlich ins Schleudern und die Ausgabe durch 
Zeile 2 erfolgt nicht. Aber dann startest du auch nicht innerhalb des 10 
Sekunden Delays sondern nur irgendwann nach 10 Sekunden ohne zu wissen 
wo genau die CPU sich befindet.

Sebastian M. schrieb:
> Carsten R. schrieb:
>> Mit screen_print_p funktioniert es aber. Worin besteht der Unterschied
>> der beiden Funktionen? Verwendet screen_print_p auch lcd_text oder
>> lcd_data? Wie sieht lcd_data aus?
>
> Das verwendet den Program-Space (PROGMEM). Kommt aber in der
> fehlerhaften Version zuletzt gar nicht mehr zum Einsatz.

Das ist nett, beantwortet aber leider meine Frage(n) nicht. Ich habe 
lcd_text oder lcd_data im Verdacht, beziehungsweise etwas das bei denen 
in der Nahrungskette liegt, die wir leider nicht nachverfolgen können. 
Mittlerweile wird es aber anstrengend sich die Bröckchen 
zusammenzustückeln weil man ständig im Dunkeln tappt.

von Sebastian M. (cyberseb)


Angehängte Dateien:

Lesenswert?

Vermutlich ist auch der Code interessant, der VOR main() abläuft.

Tatsächlich gibt es auch hier Unterschiede: in <__do_copy_data> macht er 
etwas anderes.

Nur wildes Raten, da ich wie gesagt noch nie ASM programmiert habe: In 
dem auskommentierten Text (der eh nie ausgeführt wird), sind keine 
Strings (korrekt gesagt char-Arrays) oder ähnliches, nur if-Vergleiche, 
Zahlenoperationen und ein paar Funktionsaufrufe. Sollten mit "data" in 
"<__do_copy_data>" z.B. Strings  gemeint sein, so würde es für mich Sinn 
ergeben, wenn die irgendwie an der Stelle in den RAM geladen werden. Der 
alte Compiler könnte einen Bug haben, der hier irgendetwas falsch macht.

Tatsächlich habe ich das gefunden, keine Ahnung, ob das damit 
zusammenhängt:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=18145

Sebastian

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sebastian M. schrieb:
> ergeben, wenn die irgendwie an der Stelle in den RAM geladen werden. Der
> alte Compiler könnte einen Bug haben, der hier irgendetwas falsch macht.

 LOL.
 Wie ist der Wert für deine High Fuse ?

 BOOTSZ1 und BOOTSZ0 auf 1 setzen.

: Bearbeitet durch User
von Sebastian M. (cyberseb)


Angehängte Dateien:

Lesenswert?

Carsten, sorry, falls ich mich nicht klar ausgedrückt habe. Ich bin auch 
schon ganz kirre und müde. Nochmal ganz einfach beschrieben:

[c]int main(void) {

   lcd_init(); // Befehl 1
   screen_print("Hello World"); // Befehl 2
   _delay_ms(10000);            // Befehl 3

   screen_print_twoLines(("Begrüßungs"), 1, ("Text"), 2); // Befehl 4

   // Timer und alles andere initialisieren
   // Programm-Hauptschleife [c]

Nach einem Compilieren und einem Flashen mit dem AVR-ISP (und dem damit 
einhergehenden Reset) läuft dieser Code zunächst einwandfrei. Auch über 
Befehl 4 hinweg.

Schalte ich die Stromversorgung des AVRs nun aber ab und wieder ein, 
funktioniert er nicht mehr. Der AVR kommt dabei nicht nichtmal über bzw. 
zu Befehl 1.

(Das mit dem Delay war wirklich Quatsch. Das sollte unterbinden, dass 
sich der RAM-Inhalt durch den späteren Code ändert. Schalte ich den AVR 
aber ab, sollte der RAM-Inhalt ja ohnehin schwinden.)

Kommentiere ich "Befehl 4" aus und flashe neu, startet der AVR immer. 
Auch nach einer Stromunterbrechung.

In dem Fall bleibt der ASM-Code für main() gleich (also Befehl 4 
auskommentiert vs. nicht, hängt an), im Gegensatz dazu, wenn ich weiter 
unten etwas im Code auskommentiere (was die vorherigen Posts von mir 
zeigen).

Gruß, Sebastian

von Tom (Gast)


Lesenswert?

Ein falscher Resetvektor würde das alles in der Tat gut erklären.

von Sebastian M. (cyberseb)


Lesenswert?

Marc V. schrieb:
> LOL.
>  Wie ist der Wert für deine High Fuse ?
>
>  BOOTSZ1 und BOOTSZ0 auf 1 setzen.

Warum LOL? (Klär mich auf!)

Die High Fuse ist auf "DE", BOOTSZ1=1 und BOOTSZ0=1. Eclipse sagt: "Boot 
Flash size=256 words start address $3F00".

Sollte passen, oder?

Gruß, Sebastian

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sebastian M. schrieb:
> Marc V. schrieb:
>> LOL.
>>  Wie ist der Wert für deine High Fuse ?
>>
>>  BOOTSZ1 und BOOTSZ0 auf 1 setzen.
>
> Warum LOL? (Klär mich auf!)
>

 Sorry, war nicht böse gemeint und war für mich selbst gedacht.


> Die High Fuse ist auf "DE", BOOTSZ1=1 und BOOTSZ0=1. Eclipse sagt: "Boot
> Flash size=256 words start address $3F00".
> Sollte passen, oder?

 Ja.
 Zu deinen Routinen:

 Da werden Daten aus Flash ins RAM kopiert und zwar kopiert die Routine
 links (alte ?) 1462Bytes von der Flashadresse 31004 nach RAMadresse
 0x100 (da fangen Variablen an).
 31004 + 1462 = 32466

 Die Routine rechts kopiert genauso viele Bytes aber von der
 Flashadresse 29674 nach RAMadresse 0x100.
 29674 + 1462 = 31136

 Deswegen dachte ich, dass die Boot Flash Size größer ist.

 Aber auf jeden Fall bleiben dir somit nur 586 Bytes für Stack und
 andere Variablen.
 Ob das genug ist ?
 Oder andere Variablen die du später deklarierst, überschreiben das.

von Sebastian M. (cyberseb)


Lesenswert?

OH GOTT, BOOTRST war auf 1. Setze ich das Bit auf 0, funktioniert es.

Ich glaube, dass es das war.

Und mir ist das nicht aufgefallen weil avrdude immer ein Problem mit dem 
Auswerten des zurückgelesenen Flashs hat (siehe unten) und anschließend 
nicht mehr die Fuses setzt ...

Aber warum hat sich das nicht früher bemerkbar gemacht?

Marc, herzlichen Dank für Deine Erklärungen - ich werde das morgen 
versuchen zu verstehen und nachzuvollziehen. Im Moment ist mein Hirn 
ziemlich am Ende.

Die 586 Byte sollten reichen, habe wenig Rekursion drin und den (neuen) 
Code inzwischen schon stark optimieren können.

Viele Grüße,
Sebastian

1
Reading | ################################################## | 100% 9.32s
2
3
avrdude: verifying ...
4
avrdude: 32466 bytes of flash verified
5
avrdude: reading input file ""
6
avrdude: error opening : No such file or directory
7
avrdude: input file  auto detected as invalid format
8
avrdude: can't open input file : No such file or directory
9
avrdude: read from file '' failed

von Tom (Gast)


Lesenswert?

Der falsche Resetvektor springt halt da hin, wo der Bootloader wäre. 
Wenn dein Programm kleiner ist, ist da bis zum Ende FF. Dann ist das 
kein Problem...
Wenn dein Programm größer ist, steht da Code. Und dann hängt sich der 
Chip auf, stürzt ab, oder läuft mittendrin uninitialisiert an.

von Carsten R. (kaffeetante)


Lesenswert?

Sebastian M. schrieb:
> Nach einem
> Reset ist er (meistens!) allerdings wie tot oder startet "seltsam" (z.B.
> mit Verzögerung).

Freut mich, daß das Rätsel gelöst wurde. Mir ist nur nicht klar wie das 
damit zusammenpasst. Oder wurde da zwischendurch eine neue Version 
geflasht und nicht einfach nur neu gestartet?

Für die Zukunft solltest Du dir angewöhnen systematisch alle 
Detailänderungen zu überprüfen. Wenn etwas plötzlich nicht mehr 
funktioniert hilft eine allgemeine Beschreibung nicht. Erstelle eine 
präzise Schritt für Schritt Anleitung, so daß jeder sie nachvollziehen 
kann ohne Dinge hellseherisch anzunehmen. Das ist nicht nur für uns, 
sondern in erster Linie für Dich. Der Teufel steckt ja bekanntlich im 
Detail. Dies ist da mal wieder ein Beispiel dafür.

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
Noch kein Account? Hier anmelden.