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


von Christian I. (alloc)


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:
1
uint16_t adc2voltage(uint16_t adc_value)
2
{
3
  return (625 * (uint32_t)adc_value) / 128;
4
}

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:
1
void dec2str(int32_t wert, uint8_t anzahl, uint8_t fuell, uint8_t *dest)
2
{
3
  uint8_t i;
4
  uint8_t sign = fuell;
5
  if (wert < 0) {
6
    sign = '-';
7
    wert *= -1;
8
  }
9
  for (i = 0; i < anzahl; i++)
10
  {
11
    dest[anzahl - i - 1] = '0' + (wert % 10);
12
    wert /= 10;
13
  }
14
15
  for (i=0; i<(anzahl - 1); i++)
16
  {
17
    if (dest[i] == '0')
18
      dest[i] = fuell;
19
    else
20
      break;
21
  }
22
  dest[0] = sign;
23
}
24
25
int main() {
26
...
27
  uint32_t mv = adc2voltage(adc_value); // adc_value kommt von ADC
28
29
  uint8_t str[9];
30
  str[8] = 0;
31
  dec2str(adc_value, 8, ' ', str);
32
  lcd_gotoxy(12, 0);
33
  lcd_puts(str);
34
...
35
}

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

von Werner B. (werner-b)


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

von Tobi (Gast)


Lesenswert?

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

von Christian I. (alloc)


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

von (prx) A. K. (prx)


Lesenswert?

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

von Christian I. (alloc)


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

von Christian I. (alloc)


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

von Tobi (Gast)


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 :-)

von (prx) A. K. (prx)


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.

von Christian I. (alloc)


Lesenswert?

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

Grüße,
Chris

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.