www.mikrocontroller.net

Forum: Compiler & IDEs Fehler im Compiler oder bei mir ?


Autor: Top Soft (topsoft)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich glaube einen Fehler im Compiler entdeckt zu haben. Vieleicht? 8)
+0000003B:   91200062    LDS     R18,0x0062       Load direct from data space
44:           if (Status_Relais == 0){                // wenn das Relais aus ist
+0000003D:   2322        TST     R18              Test for Zero or Minus
+0000003E:   F4C1        BRNE    PC+0x19          Branch if not equal 
Das sagt mir ja das der Compiler die Variable 'volatile uint8_t 
Status_Relais' im Ram an die Adresse 0x0062 gelegt hat.
46:               if (Anzahlpulse > 50){                  // mindestanzahl von Pulsen erreicht?
+00000046:   91800065    LDS     R24,0x0065       Load direct from data space
+00000048:   91900066    LDS     R25,0x0066       Load direct from data space
+0000004A:   97C3        SBIW    R24,0x33         Subtract immediate from word
+0000004B:   F010        BRCS    PC+0x03          Branch if carry set
Und hier liegt 'volatile uint16_t Anzahlpulse' an Adresse 0x0065 & 66 im 
Ram.
45:             if (Zeit > 257){                    // längere Zeit keine Pulse mehr gekommen
+0000003F:   91800000    LDS     R24,0x0000       Load direct from data space
+00000041:   91900064    LDS     R25,0x0064       Load direct from data space
+00000043:   5082        SUBI    R24,0x02         Subtract immediate
+00000044:   4091        SBCI    R25,0x01         Subtract immediate with carry
+00000045:   F3C8        BRCS    PC-0x06          Branch if carry set
Hier aber passt es nicht mehr, jetzt müsste die Variable 'volatile 
uint16_t Zeit' ja an Adresse 0x0000 & 0x0064 liegen. Das kann aber aus 
zwei Gründen nicht sein. Die Adresse 0x0000 sollte das Register R0 sein, 
ist also nicht im Ram. Und folgender Code wiederspricht dem:
83:         Zeit = 0;                          // Zeitzähler löschen
+000000AE:   92100064    STS     0x0064,R1        Store direct to data space
+000000B0:   92100063    STS     0x0063,R1        Store direct to data space
Diesem Code nach liegt sie aber an 0x0063 & 64, was ja auch passen 
würde.

Übersehe ich hier was oder ist das ein Fehler vom Compiler?

Gruß Rene

Autor: ATU Fan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kannst du niocht schlafen oder was

Autor: Top Soft (topsoft)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vieleich, vieleicht auch nicht. Aber was hat das mit meiner Frage zu 
tun?

Gruß Rene

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn die Optimierung eingeschaltet ist, kann der Compiler eine ganze 
Menge machen, was für den Menschen nicht auf den ersten Blick 
verständlich ist. Möglicherweise steht in R0 ja genau der Wert der an 
der Stelle benötigt wird. Ist aus den Codeschnipseln nicht zu erkennen.

Die einzig wichtige Frage hier lautet: _Tut der Code das was er soll?_

Autor: Top Soft (topsoft)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Die einzig wichtige Frage hier lautet: _Tut der Code das was er soll?_"

Nein tut er nicht.

"Möglicherweise steht in R0 ja genau der Wert der an
der Stelle benötigt wird."

kann eigentlich nicht sein Variable ist ja volatile.

Gruß Rene

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Output sieht nach dem Disassembler-Fenster vom AVR-Studio aus. Ich 
meine, ich hätte ähnliches auch schon gehabt, was aber ein Fehler vom 
AVR-Studio war. Schau also besser erstmal im HEX-File nach, was 
tatsächlich dort steht.
Oder schau in das LSS-File, auch dem würde ich eher trauen, als dem 
AVR-Studio.

Autor: Detlev T. (detlevt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Top Soft wrote:
> kann eigentlich nicht sein Variable ist ja volatile.

Das heißt aber nicht, dass der Compiler in jeder Mikrosekunde damit 
rechnet, dass dieser Wert geändert wird. Das ginge schon deshalb nicht, 
weil zum Beispiel 16-Bit-Variablen in einem 8-Bit-AVR nicht atomar 
gelesen oder geschrieben werden können.

Es geht, so wie ich das verstanden habe, eher darum, dem Compiler 
mitzuteilen, dass eine Variable außerhalb des aktuellen Blocks (oder 
Funktion?) geändert werden kann, um bestimmte Optimierungen zu 
verhindern. Wie zum Beispiel so etwas:
volatile uint8_t timer_count = 0;

while(1)
  {
    /* Tue irgendwas ohne timer_count zu ändern */
    if(timer_count > 50) / * Tue was anderes */;
   }
Ohne volatile könnte er hier die if-Abfrage wegoptimieren.

Um auf dein Beispiel zurück zu kommen. Ich vermute, dass zu diesem 
Zeitpunkt der Wert aus Adresse 0x0063 aus einer vorherigen Berechnung 
noch in dem temporären Register R0 ist. Das läßt sich aus den 
Schnipseln, die du präsentiert hast, natürlich nicht ablesen. Dann wäre 
der Code weder falsch noch langsamer als wenn man aus Adresse 0x0063 
lesen würde.

Autor: Top Soft (topsoft)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

scheint wohl wirklich am AVR-Studio zu liegen. Hier der Ausschnitt aus 
der main.sym .
00800060 b ct1.1354
00800061 b ct0.1353
00800062 b Status.1328
00800063 B Zeit
00800065 B Anzahlpulse
00800067 B key_press
00800068 B key_state

Wenn ich das sei() und cli() aus dem folgenden Code entferne habe ich 
den Fehler sonnst nicht. Schon komisch.
  while(1){
    if (Status.Relais == 0){                // wenn das Relais aus ist
      cli();                          // Interrupts aus wegen 2 Byte Variablen
      if (Zeit > 500){                    // längere Zeit (ca 5 sec) keine Pulse mehr gekommen
        if (Anzahlpulse > 50){                  // mindestanzahl von Pulsen erreicht?
          PORTB |= (1<<PB0);                    // Relais an PB0 ein
          Status.Relais = 1;                    // neuen Relaisstatus setzen
        }
        else{                          // mindestzahl von Pulse nicht ereicht!
          Anzahlpulse = 0;                    // Pulsezähler löschen
          Zeit = 0;                        // Zeitzähler löschen
        }
      }
      sei();                          // Interrupts wieder an
    }
    else{                          // wenn das Relais an ist
      if( get_key_press( 1<<KEY0 )){              // ist Taste gedrückt?
        PORTB &= ~(1<<PB0);                  // Relais an PB0 aus
        Status.Relais = 0;                    // neuen Relaisstatus setzen
      }
    }
  }

Gruß Rene

Autor: bingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schon alleine wenn ich das hier sehr wird mir schlecht


else{                          // wenn das Relais an ist
      if( get_key_press( 1<<KEY0 )){              // ist Taste gedrückt?
        PORTB &= ~(1<<PB0);                  // Relais an PB0 aus
        Status.Relais = 0;


du springst in die else und frägst dann was mit if ab
und was machste wenn die if nicht war ist

Autor: Top Soft (topsoft)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Ich vermute, dass zu diesem Zeitpunkt der Wert aus Adresse 0x0063 aus 
einer vorherigen Berechnung noch in dem temporären Register R0 ist. Das 
läßt sich aus den Schnipseln, die du präsentiert hast, natürlich nicht 
ablesen. Dann wäre der Code weder falsch noch langsamer als wenn man aus 
Adresse 0x0063 lesen würde."

Nicht langsamer? LDI braucht 3 Takte, wenns schon im Register ist braut 
es keinen!

Gruß Rene

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Hier der Ausschnitt aus der main.sym .

Das war jetzt aber die falsche Stelle zum nachschauen, denn was sagt das 
aus über den erzeugen Assembler-Code?

Autor: Top Soft (topsoft)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"du springst in die else und frägst dann was mit if ab
und was machste wenn die if nicht war ist"

ja nix, wo liegt das Problem?

Gruß Rene

Autor: Top Soft (topsoft)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Das war jetzt aber die falsche Stelle zum nachschauen, denn was sagt 
das
aus über den erzeugen Assembler-Code?"

nichts, aber über die Lage der Variablen im Ram.

Gruß Rene

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bingo wrote:

> du springst in die else und frägst dann was mit if ab
> und was machste wenn die if nicht war ist

Na nichts. Was soll daran problematisch sein?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Top Soft wrote:

> nichts, aber über die Lage der Variablen im Ram.

Die stand doch schon im ersten Post fest.
Du weißt aber immer noch nicht, ob da nun tatsächlich "LDS R24,0x0000" 
im Code steht, oder nicht.

Autor: Detlev T. (detlevt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Top Soft wrote:
> Nicht langsamer? LDI braucht 3 Takte, wenns schon im Register ist braut
> es keinen!

Sehr witzig! Ich meinte selbstverständlich "LDI R24,0x0063" im Vergleich 
zu "LDI R24,0x0000". Natürlich könnte man hier die Subtraktion gleich 
auf R0 ausführen und noch ein paar Byte und Taktzyklen sparen. Es wird 
immer wieder Fälle geben, wo der vom Compiler erzeugte Code etwas 
schlechter ist als ein von Hand optimierter.

Nachtrag: Welche Optimierungs"stufe" hast du überhaupt aktiviert. 
Vielleicht kann das der Compiler sogar noch verbessern.

Autor: Top Soft (topsoft)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja ok liegt definitiv am AVR Studio. Hier das main.lss:
if (Zeit > 500){                    // längere Zeit (ca 5 sec) keine Pulse mehr gekommen
  7a:  80 91 63 00   lds  r24, 0x0063
  7e:  90 91 64 00   lds  r25, 0x0064
  82:  85 5f         subi  r24, 0xF5  ; 245
  84:  91 40         sbci  r25, 0x01  ; 1
  86:  a8 f3         brcs  .-22       ; 0x72 <main+0x20>

Gruß Rene

Autor: Top Soft (topsoft)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Sehr witzig! Ich meinte selbstverständlich "LDI R24,0x0063" im 
Vergleich
zu "LDI R24,0x0000"."

Schon klar, aber es drängte aus mir. ;-))

Nacht Rene

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Detlev T.:

Wenn der Compiler hier tatsächlich vor hätte r0 zu verwenden (und ich 
bin nicht deiner Meinung, dass er es hier dürfte), dann würde er das 
ganz sicher nicht mit einem LDS auf Adresse 0 machen.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ja ok liegt definitiv am AVR Studio.

Das gute Studio macht zwar ab und zu mal Ärger, aber C-Code compiliert 
es niemals falsch. Garantiert.

Das Studio compiliert nämlich überhaupt keinen C-Code nichts, das macht 
der avr-gcc aus dem WinAVR-Paket. Und da wäre die erste Frage:
Welche WinAVR-Version ist installiert?

Und:
Kannst du mal einen vollständigen, kompilierbaren Code anhängen, und 
nicht nur Ausschnitte? Dazu das Studio-Projekt-File.

Oliver

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Studio kompiliert nix, aber es disassembliert sehr wohl. Und um den 
Output vom integrierten Disassembler geht es ja offenbar. Wie oben schon 
erwähnt zeigt das LSS-File den korrekten Code, WinAVR kommt also nicht 
als Schuldiger in Frage.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun ja, die beiden gezeigten Disassembler-Beispiele stammen nicht vom 
selben Source-Code:

oben:
>45:             if (Zeit > 257){                    // längere Zeit keine >Pulse 
mehr gekommen

weiter unten (aus main.lss)
>if (Zeit > 500){                    // längere Zeit (ca 5 sec) keine Pulse >mehr 
gekommen

und im oberen Beispiel ist die Disassemblierung auch richtig:
>+0000003F:   91800000    LDS     R24,0x0000

Wenn überhaupt, dann ist der Hexcode schon falsch, oder wird falsch 
gelesen.

Wo und warum da das Problem auftritt, ist wohl noch nicht so ganz klar.

Oliver

Autor: Top Soft (topsoft)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"die beiden gezeigten Disassembler-Beispiele stammen nicht vom
selben Source-Code:"

doch ich habe nur zwischenzeitlich am Code weitergearbeitet und den 
vorher willkürlich gewählten Zahlenwert durch denn korrekten ersetzt.

"Wenn überhaupt, dann ist der Hexcode schon falsch, oder wird falsch
gelesen."

der Hexcode ist korrekt, er wird falsch gelesen.

Gruß Rene

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.