www.mikrocontroller.net

Forum: Compiler & IDEs [AVR] (Fehlerhafte) Codeoptimierung bei 32bit-Variablen


Autor: Christian Illy (alloc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi alle,

sitze hier zur Zeit an einem Code, der den 10 bit ADC-Wert nach mV 
umwandeln soll. Die Rechnung ist da ja prinzipiell einfach:
mv = 5000 * adc / 1024
gekürzt:
mv = 625 * adc / 128
Da adc nun aber bereits 10 bit breit ist, 625 nochmal 10 bit, könnte das 
Ergebnis also 20 bit breit werden. Das passt nicht mehr in einen uint16, 
also dachte ich, ich nehme einfach einen uint32 her.

Die Umwandlungsroutine sieht dann jetzt so aus:
uint16_t adc2voltage(uint16_t adc_value)
{
  return (625 * (uint32_t)adc_value) / 128;
}

Verifizieren tu ich die Rechnung durch Ausgabe des Wertes auf einem 
LC-Display und einer vorrangehenden Umwandlung des Ergebnisses in einen 
String mit folgender Funktion:
void dec2str(int32_t wert, uint8_t anzahl, uint8_t fuell, uint8_t *dest)
{
  uint8_t i;
  uint8_t sign = fuell;
  if (wert < 0) {
    sign = '-';
    wert *= -1;
  }
  for (i = 0; i < anzahl; i++)
  {
    dest[anzahl - i - 1] = '0' + (wert % 10);
    wert /= 10;
  }

  for (i=0; i<(anzahl - 1); i++)
  {
    if (dest[i] == '0')
      dest[i] = fuell;
    else
      break;
  }
  dest[0] = sign;
}

int main() {
...
  uint32_t mv = adc2voltage(adc_value); // adc_value kommt von ADC

  uint8_t str[9];
  str[8] = 0;
  dec2str(adc_value, 8, ' ', str);
  lcd_gotoxy(12, 0);
  lcd_puts(str);
...
}

Wenn ich nun die Codeoptimierung aus habe (-O0), dann funktioniert der 
Code auch einwandfrei und es wird die korrekte Spannung angezeigt. Wenn 
ich die Codeoptimierung aktiviere (egal welches Level), kommen ziemlich 
krumme Werte raus. Aktuell zeigt mir das Display für einen ADC-Wert von 
50 einen Spannungswert von 64049. Bei 49 kommt 62767.

Wenn ich bei aktivierter Optimierung allerdings adc_valze einen festen 
Wert vor der Umwandlung zuordne (zB adc_value = 50), dann stimmt das 
Ergebnis auch wieder (244 mV), allerdings scheint der Compiler dann die 
Umwandlungsroutine einfach komplett wegzuoptimieren (nach meinen kurzen 
einblicken in das Listung zu urteilen ;) ).

Version des AVR-GCC ist 4.3, irgendwo meine ich mal gelesen zu haben, 
dass es da Probleme geben könnte ... Kommt nun wirklich der GCC einfach 
nicht mit den 32 bit klar, oder ist da sonst irgendwas von mir falsch?

Grüße,
Chris

Autor: Werner B. (werner-b)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bist du sicher dass du die aktuellste 4.3 WinAVR Version hast?

Installier erst mal die letzte WinAVR 20080610 von
http://sourceforge.net/projects/winavr/
und versuche es noch einmal.

Gruß
Werner

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Variablen, die nicht optimiert werden sollen, mit "volatile" 
deklarieren!

Autor: Christian Illy (alloc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Werner,

> Bist du sicher dass du die aktuellste 4.3 WinAVR Version hast?
Im Gegenteil, bin mir sogar sicher, dass es nicht WinAVR ist ;)
Hab wohl vergessen zu erwähnen, dass ich unter Linux arbeite. Habe die 
Pakete aus den offiziellen stable Ubuntu-APT-Repositories (8.10).

Grüße,
Chris

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine ungepatchte 4.3.0 Version hat einen ganz üblen Bug bei 32bit 
Multiplikation mit Konstanten, und exakt das ist hier der Fall.

Autor: Christian Illy (alloc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Tobi,

> Die Variablen, die nicht optimiert werden sollen, mit "volatile"
> deklarieren!
das habe ich schon versucht ... sowohl bei der Deklaration der 
adc_value-Variablen im Hauptcode, als auch mit ner extra 
zwischen-Variablen in der adc2voltage-Routine ... Hat beides nichts 
geändert.

Grüße,
Chris

Autor: Christian Illy (alloc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi A.K.,

> Eine ungepatchte 4.3.0 hat einen ganz üblen Bug bei 32bit Multiplikation
> mit Konstanten, und exakt das ist hier der Fall.
Dann nehme ich mal an, es gibt bereits einen Patch ... Dh ich muss 
entweder warten, bis der Patch es in die Repositories geschafft hat oder 
aus den Quellen kompilieren? Gefällt mir eigentlich beides nicht ;)
Das betrifft aber nur den GCC selber, also keine der andren Tools in der 
Toolchain?

Chris

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So wie's aussieht ist's der Compilerbug!
Ich habe noch die GCC Version 4.2.2 Und solange die neuren Versionen 
wohl nicht richtig gehen (auch bzgl. Codegrösse!), bleibe ich dabei :-)

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Yep, betrifft nur GCC. Schau dir ggf. mal den erzeugten Code an.

WinAVR basierend auf 4.3.0 wurde mehrfach zurückgezogen, einmal aufgrund 
dieses Bugs. Könnte mir vorstellen, dass Ubuntu davon nichts mitbekommen 
hat.

Autor: Christian Illy (alloc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, danke euch allen. Dann ist wenigstens wohl der Code an sich nicht 
total falsch ;)

Grüße,
Chris

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.