mikrocontroller.net

Forum: Compiler & IDEs Compiler übersetzt nur Müll


Autor: Giantics (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Selbst bei einfachen Programmen kommt bei mir manchmal nicht das
erwünschte Ergebnis aus dem Compiler (avr-gcc (GCC) 3.4.3; Atmega8).
Selbst einfache For-schleifen bringen ihn manchmal zum Aufhängen (der
verwendete Variablentyp stimmt). Wenn man dann die Optimierung
ausschaltet, dann gehts manchmal plötzlich! Also programmiert man
gemütlich so weiter. Und irgendwann mit einer ganz harmlosen Zeile Code
dreht der Controller wieder durch. Wenn man dann Glück hat, gehts mit
einer anderen Optimierungsstufe wieder. Irgendwann war ich dann an dem
Punkt, an dem keine Optimierungsstufe mehr einwandfrei funkioniert hat.
Aber in jeder ging irgendwas anderes nicht. Absolut nicht
nachvollziehbar. Ich hab jetzt auch gemerkt, dass die "hex"-Datei
nicht mit der "lss"-Datei übereinstimmt (Die Adressen der Funktionen
stimmen nicht). Kann das sein? Ist das ganze eventuell eine
Einstellungssache?
Controller und Frequenz sind in der Makefile eingetragen.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wär's mit einem Beispiel?

Autor: Giantics (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/io.h>
#include <stdint.h>
#include "lcd_atmega8.h"

void main(void)
{
  unsigned int i;
  LCD_Init();
  LCD_Clr();
  DDRB= (1<<PB0) | (1<<PB5);
  PORTB=1;
  for (i=0;i<=30000;i++) ;
  PORTB|= (1<<5);
  LCD_Str("irgendwas");
  while (1);
  return 0;
}

Hin und wieder kann man kurz das Wort auf dem LCD lesen, dann ists
wieder weg und irgenwann wieder da. Im gleichen Takt wechselt der
PortB-5 seinen Zustand. PortB-0 bleibt auf 5V.
Wenn ich die Schleife und die Port-Befehle rausmache, dann filmmert das
LCD (als obs ständig aktualisiert würde).
(Optimierungsstufe 0)

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Trivial, hier ohne Belang und vom Compiler angezeigt: return in einer
void-Funktion.

Welche Schleife rausgemacht? Sind 2 drin. Ohne die zweite tät's mich
nicht wundern. Wenn sich jedoch während der while(1)-Schleife auf dem
LCD oder den Ports etwas tut, dann liegt das Problem in der Hardware,
nicht der Software. Mal vorausgesetzt, dass die LCD-Routinen keine
Interrupts verwenden.

Autor: Fritz Ganter (fritzg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei  while (1); und bei der for-schleife schreib besser

while (1)
 asm volatile ("nop");


weil sonst optimiert er die Schleife weg.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Compiler optimiert nur Dinge weg, die aus seiner keine Wirkung
haben. Die while(1)-Schleife aber darf er nicht wegoptimieren, da sonst
der Code dahinter ausgeführt würde.

Nicht zu verwechseln mit Zählschleifen. Da kann's schon sein, dass aus
for (i=1;i!=1000;++i); am Ende ein einfaches i=1000 wird.

Autor: Giantics (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Konnte es noch weiter eingrenzen:
void main(void)
{
  unsigned int i;
  DDRB= (1<<PB0) | (1<<PB5);
  PORTB=1;
  for (i=0;i<=30000;i++) ;
  PORTB|= (1<<5);
  while (1) ;//asm volatile ("nop")
  return 0;
}
So bleibt PortB auf 1 stehen (d.h. er macht ab der For-Schleife nicht
mehr das, was er soll. Wenn ich jedoch das "asm..." in der while
Schleife eintrage, dann gehts wunderbar. Aber wieso passiert das mit
der Optimierungsstufe 0? In der "lss"-Datei steht der Befehl (rjmp
-2) noch drin. In der Hex stimmt dann gar nix mehr überein!
Außerdem war dies auch nur ein kleines Beispiel meiner Probleme. Bei
größeren Projekten habe ich keine Chance mehr irgendwas zu
kontrollieren. Da optimiert er einfach Sachen weg, obwohl sie nötig
sind. Ich habe keine Ahnung mehr was ich da machen kann. Hat von euch
niemand solche Probleme?

Autor: Giantics (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Die Hex liegt bei.
Gibts eine Möglichkeit, dass er alles so wie in der lss-Datei auch in
die Hex übernimmt?

void main(void)
{
  5c:  cd e5         ldi  r28, 0x5D  ; 93
  5e:  d4 e0         ldi  r29, 0x04  ; 4
  60:  de bf         out  0x3e, r29  ; 62
  62:  cd bf         out  0x3d, r28  ; 61
  unsigned int i;
  //LCD_Init();
  //LCD_Clr();
  DDRB= (1<<PB0) | (1<<PB5);
  64:  81 e2         ldi  r24, 0x21  ; 33
  66:  80 93 37 00   sts  0x0037, r24
  PORTB=1;
  6a:  81 e0         ldi  r24, 0x01  ; 1
  6c:  80 93 38 00   sts  0x0038, r24
  for (i=0;i<=30000;i++) ;
  70:  19 82         std  Y+1, r1  ; 0x01
  72:  1a 82         std  Y+2, r1  ; 0x02
  74:  89 81         ldd  r24, Y+1  ; 0x01
  76:  9a 81         ldd  r25, Y+2  ; 0x02
  78:  25 e7         ldi  r18, 0x75  ; 117
  7a:  81 33         cpi  r24, 0x31  ; 49
  7c:  92 07         cpc  r25, r18
  7e:  30 f4         brcc  .+12       ; 0x8c
  80:  89 81         ldd  r24, Y+1  ; 0x01
  82:  9a 81         ldd  r25, Y+2  ; 0x02
  84:  01 96         adiw  r24, 0x01  ; 1
  86:  89 83         std  Y+1, r24  ; 0x01
  88:  9a 83         std  Y+2, r25  ; 0x02
  8a:  f4 cf         rjmp  .-24       ; 0x74
  PORTB|= (1<<5);
  8c:  80 91 38 00   lds  r24, 0x0038
  90:  80 62         ori  r24, 0x20  ; 32
  92:  80 93 38 00   sts  0x0038, r24
  //LCD_Str("irgendwas");
  while (1) ;//asm volatile ("nop")
  96:  ff cf         rjmp  .-2        ; 0x96

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir scheint das Hex-File eigentlich ganz gut zum LSS zu passen.

Autor: A.K. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
"Da optimiert er einfach Sachen weg, obwohl sie nötig sind."

Da wäre ein konkretes Beispiel recht hilfreich - also der betreffende
C-Code und das falsche Resultat (.lst oder .lss). Im oben gezeigten
Code ist bis hin zum Hex-File alles ok.

"Hat von euch niemand solche Probleme?"

Ich selbst nicht und der allgemeinen Diskussionskultur hier nach zu
schliessen auch sonst niemand.

Anbei Disassembly vom Hex.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PORTB=1;
  for (i=0;i<=30000;i++) ;
  PORTB|= (1<<5);

"So bleibt PortB auf 1 stehen"

Ich sehe auch keinen Grund, warum der Mega8 das nicht so halten sollte.
Die erste Zeile setzt B5 auf 1, die dritte Zeile ändert B5 von 1 auf 1.
Wenn B5 da auf 0 gehen soll, dann mit
  PORTB &= ~(1<<5);

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicht ganz richtig. Nach der ersten Zeile ist PORTB 1, nach der dritten
0x21.

Autor: Giantics (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@A.K. Genau, der PortB müsste 0x21 sein, ist er aber definitiv nicht.
Ich hab mal das Hex mit dem AVR-Studio debugged und siehe da, auch hier
ist nur PB0 gesetzt nicht aber PB5!
Das deutet doch daraufhin, dass hex und lss doch nicht übereinstimmen,
oder bin ich blind? Habt ihr das hex mal ausprobiert? Oder könnte
jemand von euch mal die obigen Zeilen kompilieren und das hex hier
reinstellen, dann könnte ich sehen obs vielleicht doch an meinen
Einstellung liegt.

Autor: churchi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mit
PORTB=1; und
PORTB|= (1<<5);

ist es glaub ich kein Wunder wenn PB5 nicht gesetzt ist.
mit einem |= wird ein bit gelöscht.
mit &=~ wird es gesetzt

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist falsch.

Autor: churchi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sry - klar - warum verwechsle ich das nur immer wieder?

Autor: Fritz Ganter (fritzg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau dir mal  Zeit und Datum der .lss und .hex Datei an. Sollte
eigentlich identisch sein.

Autor: Giantics (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe die Ursache gefunden. Es liegt am Übertragungsprogramm:

Das wird reingeschickt:
0000: 12 C0 2B C0 2A C0 29 C0 28 C0 27 C0 26 C0 25 C0
0010: 24 C0 23 C0 22 C0 21 C0 20 C0 1F C0 1E C0 1D C0
0020: 1C C0 1B C0 1A C0 11 24 1F BE CF E5 D4 E0 DE BF
0030: CD BF 10 E0 A0 E6 B0 E0 E6 E9 F0 E0 02 C0 05 90
0040: 0D 92 A0 36 B1 07 D9 F7 10 E0 A0 E6 B0 E0 01 C0
0050: 1D 92 A0 36 B1 07 E1 F7 01 C0 D2 CF CD E5 D4 E0
0060: DE BF CD BF 81 E2 80 93 37 00 81 E0 80 93 38 00
0070: 19 82 1A 82 89 81 9A 81 8F 31 91 05 30 F4 89 81
0080: 9A 81 01 96 89 83 9A 83 F5 CF 80 91 38 00 80 62
0090: 80 93 38 00 FF CF

Und beim Auslesen kommt das zurück:
0000: 12 C0 2B C0 2A C0 29 C0 28 C0 27 C0 26 C0 25 C0
0010: 24 C0 23 C0 22 C0 21 C0 20 C0 1F C0 1E C0 1D C0
0020: 1C C0 1B C0 1A C0 11 24 1F BE CF E5 D4 E0 DE BF
0030: CD BF 10 E0 A0 E6 B0 E0 E6 E9 F0 E0 02 C0 05 90
0040: 0D 92 A0 36 B1 07 D9 F7 10 E0 A0 E6 B0 E0 01 C0
0050: 1D 92 A0 36 B1 07 E1 F7 01 C0 D2 CF CD E5 D4 E0
0060: DE BF CD BF 81 E2 80 93 37 00 81 E0 80 93 38 00
0070: 19 82 1A 82 89 81 9A 81 8F 31 91 05 30 F4 89 81
0080: 9A 81 01 96 89 83 9A 83 F5 CF 80 91 38 00 80 62
0090: 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Da fehlen eindeutig die letzten 2 Befehle. Werde mal schauen wo da der
Fehler liegt.
Danke für eure Hilfe!

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Übrigens, nur nebenbei: das LSS-Listing ist ein Disassemblerlisting,
das von der Ausgabe her rückwärts generiert wird und dann anhand der
Debuginformationen mit den Codeschnipseln ,,annotiert'' wird.  Das
muss ganz zwangsläufig mit der ELF-Date übereinstimmen, und sofern
nicht jemand das Extrahieren der HEX-Datei aus dem ELF verpfuscht hat,
dann auch mit dieser.

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.