[AVR] (Fehlerhafte) Codeoptimierung bei 32bit-Variablen

OP #1058626
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
OP #1058667
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
OP #1058669
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren