Forum: Mikrocontroller und Digitale Elektronik Dieses AVR Studio / debugger macht mich crasy


von Hans F. (hans_f83)


Lesenswert?

Folgender Code
1
  uint8_t keychanged=0x02;
2
3
  uint8_t i=0;  
4
5
  for ( i = 0; i<7; i++)
6
  {
7
    if (((1<<i) & keychanged) != 0)
8
    {
9
      // tu etwas
10
    }
11
  }

beim ersten Durchlauf springt der Debugger sofort in die "IF" Bedingung

i=0
keychanged=0x02
somit ist die Bedingung false
Der Debugger übergeht aber das IF Statement und springt gleich in
"tu etwas"

ist mir zu hoch
Die Optimierung steht auf -Os, -O1 geht auch nicht.
Ohne Optimierung wird mir der Code zu groß.

Schöne Weihnachtsfeiertage

Hans

von Klaus W. (mfgkw)


Lesenswert?

Hans F. schrieb:
> Der Debugger übergeht aber das IF Statement und springt gleich in
> "tu etwas"

Hans F. schrieb:
> Die Optimierung steht auf -Os

Dann kann der Compiler vielleicht merken, daß der erste Durchlauf nichts 
macht?
Wäre zumindest nachvollziehbar.

Hans F. schrieb:
> Ohne Optimierung wird mir der Code zu groß.

Dann darfst du dich aber auch nicht wundern, wenn der Compiler Code 
erzeugt, der anders abläuft wie in deinem Quelltext steht.
Bedingung ist nur, daß im Endeffekt dasselbe rauskommt.
Daß ein wirkungsloser erster Schleifendruchlauf auch wirklich ausgeführt 
wird, steht nicht in den Spielregeln, wenn man mit Optimierung arbeitet.

Wo ist das Problem?

Hans F. schrieb:
> Der Debugger übergeht aber das IF Statement und springt gleich in
> "tu etwas"

Mit welchem Wert von i?
wird i überhaupt verwendet?


> Dieses AVR Studio / debugger macht mich crasy
Deine Sprache zieht mir die Fußnägel hoch.

Hans F. schrieb:
> Schöne Weihnachtsfeiertage

dto.

von Astro (Gast)


Lesenswert?

Debuggen geht grundsätzlich nur ohne Optimierung. Auch auf großen C++ 
Compilern für PC.
Das ist eine Grundregel die man nur einmal akzeptieren muss und dann ist 
gut. Deshalb den Controller immer eine Nummer größer wählen.

von Karl H. (kbuchegg)


Lesenswert?

> Debuggen geht grundsätzlich nur ohne Optimierung.

@TO
Zumindest muss man damit rechnen, dass die Reihenfolge der Anweisungen 
umsortiert wird und nicht alles ganz genau so ausgeführt wird, wie es 
der Programmierer niedergeschrieben hat. Sonst wärs ja auch keine 
Optimierung, denn dazu muss der Compiler ja schliesslich irgendwas 
verändern.
Und wie schon gesagt: solange sich am #sichtbaren# Ergebnis des 
Programms nichts verändert, darf er das auch.

> Ohne Optimierung wird mir der Code zu groß.

Solange du solche Expressions wie 1<<i benutzt, schätze ich mal, dass 
man in deinem Programm noch vieles besser machen könnte.

von Hans Peter B. (Gast)


Lesenswert?

Bei solchen C-code-Zeilen:
if (((1<<i) & keychanged) != 0)
würde ich von Anfang an, die kritischen Stellen auf Assembler-Ebene 
debuggen.
Ich weiss zwar nicht, ob das  unter AVR Studio möglich ist - Der GDB/DDT 
kann es jedenfalls.
Hans Peter

von Hans F. (hans_f83)


Lesenswert?

Wenn das "sichtbare Ergebnis" gleich bleiben würde, hätte ich ja auch
nichts dagegen.

Aber genau hier ist das Problem
Beim ersten Schleifendurchlauf ist i = 0
1<<i = 0x01
keychanged = 0x02

0x01 & 0x02 ist definitiv == 0
trotzdem wird die if Bedingung true und der Code dahinter wird 
ausgeführt.
Der Debugger überspringt sogar das if Statement und springt gleich
in die nachfolgende Klammer.

 {
   // tu etwas
 }

Und Optimierung hin oder her, das Ergebnis sollte richtig sein.

@kbuchegg

Was ist gegen 1<<i auszusetzen wenn man bitweise maskieren will?
Ich bin nicht lernresistent und neugierig auf eine bessere Variante.

@ Klaus Wachtler
Na bei den Fußnägeln kann ich auch nicht helfen.
Aber wenn man >3h einen Fehler sucht, dann feststellt das der Code
nicht das macht was erwartet wird und man die Ursache nicht ergründen
kann, geht halt schon mal der Gaul durch.
Nach mehr als 25 Jahren Programmierung macht mich das halt crazy.

Nix für ungut.
Ich hab das ganze sogar in Einzelstatements zerlegt mit dem gleichen
Ergebnis.

@Hans Peter
Die Möglichkeit habe ich im AVR Studio noch nicht gefunden.
Wobei ich die Zeile nicht als kritisch ansehe.

@Astro
Die Einstellung -O1 ist default beim AVR Studio.
Somit hätte ich schon erwartet, das diese auch brauchbare Ergebnisse
liefert. Zumindest sollte das Resultat nicht falsch sein.


In dem Sinne

Immer ein Bit übrighalten :)

Hans

von Achim S. (Gast)


Lesenswert?

kann zwischen

 uint8_t keychanged=0x02;

und dem Aufrauf der Schleife irgendwo der Wert von keychanged geändert 
werden? Fall nicht, weiß der Compiler schon, dass der "tue etwas" Teil 
genau nur einmal aufgerufen wird (nämlich für i==1). Dann kann er sich 
Schleife und if-Abfrage sparen.

Klaus Wachtler schrieb:
> Mit welchem Wert von i?
> wird i überhaupt verwendet?

Das ist die relevante Frage. Wird im "tue etwas" Teil i wirklich falsch 
benutzt? Was ist denn das falsche Ergebnis, das sich daraus ergibt? Dass 
der Debugger einen direkten Einsprug anzeigt, ohne zuvor auf einigen 
nicht benötigten Code-Zeilen herumzuspringen, ist noch kein falsches 
Ergebnis.

Achim S.

von Fred S. (kogitsune)


Lesenswert?

Hans F. schrieb:
> @Hans Peter
> Die Möglichkeit habe ich im AVR Studio noch nicht gefunden.
> Wobei ich die Zeile nicht als kritisch ansehe.

Gilt für Studio 6: Starte eine Debug Session, dann wähle "Debug | 
Windows | Disassembly"

von Mark .. (mork)


Lesenswert?

Hans F. schrieb:
> Was ist gegen 1<<i auszusetzen wenn man bitweise maskieren will?
> Ich bin nicht lernresistent und neugierig auf eine bessere Variante.

AVRs haben keinen Barrel-Shifter o.ä., sodass im schlimmsten Fall bei 
jeder einzelner Berechnung von (1 << i) eine Schleife durchlaufen 
werden muss, die die 1 i mal um eins nach links shiftet. Das ist langsam 
und verbraucht Speicher.

Besser wäre
1
unsigned char mask = 1;
2
for(int i = 0; i < 8; i++, mask <<= 1) {
3
    if(keychanged & mask) {
4
        tu etwas...
5
    }
6
}
MfG und frohe Weihnachten

von Karl H. (kbuchegg)


Lesenswert?

Hans F. schrieb:

> Nix für ungut.

Nix für ungut.
Aber wenn dein Code nach der Optimierung nicht mehr das tut, was du ohne 
Optimierung erwartet hast, dann ist es meistens so, dass DU einen Fehler 
gemacht hast.
Der C-Compiler und speziell der Optimizer kann besser C als 99% der hier 
anwesenden Poster und kennt die Regeln besser. Natürlich kommt es auch 
vor, das Compiler/Optimizer ferhlerhaft sind. Aber in den meisten Fällen 
ist es der Fehler des Programmierers.

Und nein: mit 'sichtbares Ergebnis' ist NICHT gemeint, dass du im 
Debugger exakt dieselbe Schritte siehst. Das kann und wird differieren. 
Mit sichtbarem Ergebnis ist alles gemeint, was du letztendlich im I/O 
sehen wirst. Seien das Pins oder Ausgaben auf ein LCD oder UART oder 
dergleichen.


Aus deinem Code kann man nichts ableiten, was denn jetzt fehlerhaft sein 
sollte, ausser das dein vom Compiler optimiertes Programm im Debugger 
nicht die Schritte macht, die du erwartet hättest. Was aber weiter nicht 
verwunderlich ist. Denn wie soll denn ein Optimizer ein Programm 
schneller machen, wenn er nichts verändern darf? Wenn da mal drüber 
nachdenkst, kommst du drauf, dass das nicht geht. Ergo wirst du im 
Debugger bei einem Programm, über welches sich der Optimizer her gemacht 
hat IMMER Differenzen in der Reihenfolge der Ausführungen sehen.

von Hans F. (hans_f83)


Lesenswert?

OK, ich denke die Problematik ist noch nicht ganz angekommen

Ich schreibs mal anders
1
 uint8_t keychanged=0x02;
2
3
  uint8_t i=0;  
4
5
  for ( i = 0; i<7; i++)
6
  {
7
    if (((1<<i) & keychanged) != 0)
8
    {
9
      printf("Wert von i = %x ",i);  
10
    }
11
  }

Ausgabe:
"Wert von i = 0"
"Wert von i = 1"

Erwartet hätte ich:
"Wert von i = 1"
aber nicht
"Wert von i = 0"

so und jetzt wird Zeit für die Familie

wünsche allen ein schönes Weihnachtsfest

Hans

von Karl H. (kbuchegg)


Lesenswert?

Hans F. schrieb:
> OK, ich denke die Problematik ist noch nicht ganz angekommen
>
> Ich schreibs mal anders
>
>
1
>  uint8_t keychanged=0x02;
2
> 
3
>   uint8_t i=0;
4
> 
5
>   for ( i = 0; i<7; i++)
6
>   {
7
>     if (((1<<i) & keychanged) != 0)
8
>     {
9
>       printf("Wert von i = %x ",i);
10
>     }
11
>   }
12
>
>

Und das ist TATSÄCHLICH dein Programm, welches dir Ärger bereitet hat?

Die Betonung liegt auf TATSÄCHLICH!
Du hilfst niemanden damit, wenn du jetzt auf die Schnelle ein Programm 
erfindest, welches NICHT dein Problem darstellt. Ich bin mir nämlich 
sehr sicher, dass dieses Programm NICHT den von dir angegebenen Output 
liefert, wenn ich ein main drumherum stricke und es laufen lasse. 
Optimizer hin oder her.

von Bernd (Gast)


Lesenswert?

Hans F. schrieb:
> OK, ich denke die Problematik ist noch nicht ganz angekommen
>
> Ich schreibs mal anders

das hilft nichts. Wenn ein Programm nicht funktioniert dann musst du 
dieses zeigen, und nicht ein anderes!

von Karl H. (kbuchegg)


Lesenswert?

Bernd schrieb:

> das hilft nichts. Wenn ein Programm nicht funktioniert

Wobei für mich der Terminus "nicht funktioniert" noch lange nicht 
nachgewiesen ist.
Eine andere Schrittfolge im Debugger zu sehen, ist noch lange nicht 
"funktioniert nicht".

Ändert aber nichts an der Feststellung, dass das exakte Programm her 
muss und man sich dessen Ergebnisse ansehen muss, um zu entscheiden, ob 
hier überhaupt ein Fehler vorliegt oder ob einfach nur seine Erwartungen 
falsch waren.

von Bernd (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> printf("Wert von i = %x ",i);

dass das nicht das Originalprogramm ist kann man auch daran erkennen 
dass der Output auch gar nicht

Wert von i = 0
Wert von i = 1

sein kann wie von Hans geschrieben

von Karl H. (kbuchegg)


Lesenswert?

Bernd schrieb:
> Karl Heinz Buchegger schrieb:
>> printf("Wert von i = %x ",i);
>
> dass das nicht das Originalprogramm ist

Ist es ganz sicher nicht.

Das beobachtete Verhalten im Debugger lässt sich ganz leicht mit einer 
Kombination aus Loop-Unrolling, Constant-Folding und Dead Code 
Elimination erklären. Alles Standardmechanismen in der Optimierung.

Das i im Debugger nicht den erwarteten Wert hat bzw. dass der 
Asuführungspfeil sofort bis in die then-Klausel vom if runterrutscht ist 
nichts beunruhigendes, solange der tu_was Teil trotzdem des Korrekte 
macht. Und bis jetzt gibt es keine gegenteilige Aussage (die printf 
Variante nehm ich jetzt mal nicht ernst)

von Oliver (Gast)


Lesenswert?

Hans F. schrieb:
> OK, ich denke die Problematik ist noch nicht ganz angekommen

Ist sie. Voll und ganz.

Was dir weiter oben schon mal jemand sagen wollte: Vergiß einfach, was 
du im Debugger siehst. Gerade die avr-Debugger zeigen bei optimiertem 
Code Dinge an, die nichts mit dem tatsächlichen Programmablauf zu tun 
haben. Da kommt schlicht die Zuordnung des Assembler-Codes zu den 
C-Cource-Zeilen durcheinander. Entweder debuggst du ohne Optimierung, 
wenn das gar nicht passt, versuch mal mit -O1. Alternativ nimm zum 
Debuggen einen Prozessor aus der gleichen Familie mit mehr Speicher.

Solange du allerdings solche trivialen Dinge untersuchst, solltest du 
dein Programm abspecken, und Modul für Modul testen. Dann passt es auch 
wieder ohne Optimierung in den Speicher.

Oliver

von Hans F. (hans_f83)


Lesenswert?

@all

So das Programm läuft jetzt. :)

Ich weis zwar noch nicht 100% warum, aber der Tip von Mark brachte
den Durchbruch.

Das Source Snippet ist nicht 100% das gleiche, führte aber zum gleichen
(falschen) Ergebnis.

Das Statement
printf("Wert von i = %x ",i);

war nur symbolhaft, macht auf dem AVR so ja auch nicht viel Sinn.
Der Rumpf war aber identisch.

Den kompletten Source gibts später mal, sobald das Gesamtprojekt zur
Zufriedenheit läuft.

Dank an alle die hier unterstützt haben.

Gruß Hans

von Bernd (Gast)


Lesenswert?

Hans F. schrieb:
> Ich weis zwar noch nicht 100% warum, aber der Tip von Mark brachte
> den Durchbruch.
damit hast du dein "Problem" das keines war "gelöst":
vermutlich kann der Compiler jetzt nicht mehr optimieren und führt die 
Schleife deshalb aus
>
> Das Source Snippet ist nicht 100% das gleiche, führte aber zum gleichen
> (falschen) Ergebnis.
Unsinn

Hans F. schrieb:
> Nach mehr als 25 Jahren Programmierung macht mich das halt crazy.

nach 25 Jahren Programmierung solltest Du eigentlich wissen das es auf 
jedes Komma ankommt und das man deshalb (im Gegensatz zu Doktorarbeiten) 
immer die ORIGINAL-Source mit Copy and Paste posten muss!

von Hans F. (hans_f83)


Lesenswert?

Bernd schrieb:
> damit hast du dein "Problem" das keines war "gelöst":
> vermutlich kann der Compiler jetzt nicht mehr optimieren und führt die
> Schleife deshalb aus

Mein lieber Bernd,

das hier ist ein Hobby Projekt und soll es auch bleiben.
Für mich kommt es mehr darauf an das Ziel zu erreichen, als jedes Bit zu
analysieren und auch noch die letzte Schleife zu optimieren.
Das Projekt soll schließlich auch mal fertig werden und zum Einsatz 
kommen.
Auch hierzu gibt es einen persönlichen Zeitrahmen.

Sicher interessiert es mich, warum die obrige Variante nicht
funktioniert, ich bin aber nicht bereit unendlich viel Zeit in die
Analyse zu stecken.
Es gibt wichtigeres im Leben als dies.

Die jetzige Lösung führt nicht nur zum Ziel, sondern ist darüber hinaus
auch performanter, wobei letzters hier keine Rolle spielt.

Damit gilt das Problem für mich als "gelöst".

Im übrigen ist es völlig belanglos, was in dem IF Statement passiert,
da hier nichts das Fehlverhalten beeinflußt.

Nebenbei bemerkt, ist es auch in der kommerziellen Software Entwicklung
häufig so, das ein Problem durch einen "Workaround gelöst wird."

Dies kann unterschiedliche Ursachen haben:
Sei es das ein Problem in einem Software Addon eines Zulieferers liegt,
das sich kurzfristig nicht ändern läßt, oder der Zulieferer an einer
Änderung nicht interessiert ist.

Oder sei es ganz einfach das der Termin und Projektdruck eine 
ausführliche
Analyse nicht zuläßt, da eine Überschreitung des Zeit / Budgetrahmens
enorme Kosten und Regressansprüche nach sich zieht.

Es gibt viele Wege zum Ziel und nicht immer ist der kürzeste auch der
optimalste.

Und damit möchte ich diese Diskussion hier beenden.

Ich bedanke mich bei allen die "Zielorientiert" zur Lösung beigetragen
haben.


Hans

von Karl H. (kbuchegg)


Lesenswert?

Hans F. schrieb:

> Sicher interessiert es mich, warum die obrige Variante nicht
> funktioniert,

Der speingende Punkt ist: sie hat funktioniert.
Dein Problem war ein ganz anderes: Du hast das was du im Debugger 
gesehen hast falsch interpretiert.

> ich bin aber nicht bereit unendlich viel Zeit in die
> Analyse zu stecken.

Falscher Ansatz.
Wenn du ein Haus baust und es stürzt dir ein, dann musst du rausfinden 
warum.

> Damit gilt das Problem für mich als "gelöst".

Ein Problem ist niemals gelöst, solange man nicht die Ursachen kennt, 
die zum Problem geführt haben.
Das was du in deinem Eröffnungsposting erzählt hast, war es jedenfalls 
sehr sehr wahrscheinlich nicht. Du hast sozusagen lediglich deine 
Messinstrumente falsch interpretiert. Warum dir aber der Kernreaktor um 
die Ohren geflogen ist, hast du damit aber nicht erklärt.

> Im übrigen ist es völlig belanglos, was in dem IF Statement passiert,
> da hier nichts das Fehlverhalten beeinflußt.

Irrtum.
Genau das beeinflusst es. Denn es steuert, welche Optimierungen der 
Compiler in welcher Form anwenden kann. Und da du im optimierten Code 
debuggen willst/musst, musst du dieses Verhalten kennen und mit 
einbeziehen um nicht dem Trugschluss zu verfallen, dem du zum Opfer 
gefallen bist. Du bist einem Phantom hinterher gejagt.

> Nebenbei bemerkt, ist es auch in der kommerziellen Software Entwicklung
> häufig so, das ein Problem durch einen "Workaround gelöst wird."

Bitte nenn uns die Firma. Damit wir in Zukunft einen großen Bogen um 
diese 'Softwarebude' machen können.

> Sei es das ein Problem in einem Software Addon eines Zulieferers liegt,
> das sich kurzfristig nicht ändern läßt, oder der Zulieferer an einer
> Änderung nicht interessiert ist.
>
> Oder sei es ganz einfach das der Termin und Projektdruck eine
> ausführliche
> Analyse nicht zuläßt, da eine Überschreitung des Zeit / Budgetrahmens
> enorme Kosten und Regressansprüche nach sich zieht.

Du redest von ganz anderen Dingen.
Bei dir dreht es sich an dieser Stelle nicht um Zulieferer, die 
ausfallen oder um eng gesteckte Zeitrahmen. Bei dir dreht es sich darum, 
dass du schlicht und ergreifend mit deinem Werkzeug nicht umgehen 
kannst. Brutal gesagt.

von Hans F. (hans_f83)


Lesenswert?

Ich werde das nicht weiter kommentieren.
Auf dieses Niveau zieht mich niemand herunter!!!

Gut möglich das ich einem Phantom hinterhergejagt,
Oder einfach den Eigenheiten des Compilers  erlegen bin.

Das alles ist aber kein Grund diesen Ton anzuschlagen.

von Karl H. (kbuchegg)


Lesenswert?

Hans F. schrieb:
> Ich werde das nicht weiter kommentieren.
> Auf dieses Niveau zieht mich niemand herunter!!!
>
> Gut möglich das ich einem Phantom hinterhergejagt,
> Oder einfach den Eigenheiten des Compilers  erlegen bin.
>
> Das alles ist aber kein Grund diesen Ton anzuschlagen.

Was erwartest du?
Du präsentierst etwas, von dem jedem hier klar ist, dass es NICHT dein 
Problem darstellst. Die Aufforderung, doch bitte ein komplettes 
nachvollziehbares Beispiel zu posten, ignorierst du geflissentlich. 
Statt dessen flüchtest du dich in eine Scheinwelt, in der es dich nicht 
interessiert, was denn eigentlich das Problem war.

Professionell ist etwas anderes.
Und es passt so gar nicht zu deinen 25 Jahren Programmiererfahrung.

von Hans F. (hans_f83)


Lesenswert?

Mein lieber Karl Heinz Buchegger,

niemand hat hier explizit nach dem kompletten Programm gefragt.

Ich habe das Ergebnis selbst nicht geglaubt.
Daher habe ich vor dem Post das ganze im 2010er Studio gedebuggt.
Wie zu erwarten, gab es hier den Fehler nicht.
Dann hab ich das Resultat incl. aller Variablen vom AVR über den UART
ausgeben lassen.
Resultat: Die If Anweisung war auch bei i=0 true.

Erst danach habe ich diesen Thread verfasst.

Im übrigen habe ich nirgendwo geschrieben, das ich 25 Jahre Erfahrung
mit der AVR Programmierung habe.
Ganz im Gegenteil, einfach mal lesen!

und was dies hier betrifft
>>Bitte nenn uns die Firma. Damit wir in Zukunft einen großen Bogen um
>>diese 'Softwarebude' machen können.

Ich nehm' dich gerne mal mit bei einem der nächsten Projekte.
Dann schau wir mal ob hinter den Sprüchen auch Taten stehen.

Aufgrund der Ausartung dieses Threads werde ich mein Projekt hier nicht
mehr zur Verfügung stellen.
Von einem Moderator erwarte ich das er "moderiert" und nicht beleidigt.


@ Frank M.
solltest du weiter Interesse an der Umsetzung haben, lass es mich 
wissen.
Ansonsten bedanke ich mich für deine tolle Unterstützung!

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.