Forum: Mikrocontroller und Digitale Elektronik Schlechte Compileroptimierung?


von Florian (Gast)


Lesenswert?

Hallo zusammen,

ich benutze in einem Programm öfters mal _delay_ms(). Leider kann man 
damit nur begrenzt lange warten, und zwar 262.14 ms / F_CPU in MHz.

Damit ich auch länger warten kann, habe ich etwas geschrieben wie

#define MAX_DELAY_MS (262 / (F_CPU / 1000000))

static void my_delay_ms(uint16_t ms) {
  while(ms > MAX_DELAY_MS) {
    ms -= MAX_DELAY_MS;
    _delay_ms(MAX_DELAY_MS)
  }
  _delay_ms(ms);
}

Wenn ich nun _delay_ms() mehrmals per Hand aufrufe, ist das Binary ca. 
500 Byte gross. Benutze ich oben genannte Hilfsfunktion, ist es fast 4KB 
gross, also um ganze 3500 Byte größer. Irgendwas läuft da doch schief, 
oder? Hat jemand eine alternative um länger als MAX_DELAY_MS zu warten 
und nicht mehrmals _delay_ms() per Hand aufrufen zu müssen?

Gruss
Flo

von Andreas K. (a-k)


Lesenswert?

Es sollte sich langsam rumgesprochen haben, dass die Delay-Funktionen 
Fliesskommarechnung zur Umrechnung von Zeiten in Takte verwenden. Was 
bei Konstanten kein Problem ist, da macht das der Compiler. Bei 
Variablen hingegen findet diese Umrechnung dann zur Laufzeit statt, 
platz- und zeitraubend.

von Andreas K. (a-k)


Lesenswert?

Ist dir das hier zu einfach?
1
static void my_delay_ms(uint16_t ms) {
2
  while (ms--) {
3
    _delay_ms(1);
4
  }
5
}

von Benedikt K. (benedikt)


Lesenswert?

Davon abgesehen können die neueren Versionen auch längere Delays.

von I_ H. (i_h)


Lesenswert?

Ich hatte das Problem auch mal, aber halt nur bei variablen delays. Hast 
du vielleicht woanders noch ein variables drinnen?

Ach ja - Optimierungen (-O2,3 oder -Os) eingeschaltet? Sonst optimiert 
er vll die Fließkommarechnung nicht weg.

von Stefan E. (sternst)


Lesenswert?

Florian wrote:

> ich benutze in einem Programm öfters mal _delay_ms(). Leider kann man
> damit nur begrenzt lange warten, und zwar 262.14 ms / F_CPU in MHz.

Hast du in der Dokumentation auch mal den nächsten Absatz gelesen?

1
When the user request delay which exceed the maximum possible one,
2
_delay_ms() provides a decreased resolution functionality. In this mode
3
_delay_ms() will work with a resolution of 1/10 ms, providing delays up
4
to 6.5535 seconds (independent from CPU frequency). The user will not be
5
informed about decreased resolution.

Oder reicht dir eine Auflösung von 1/10 ms nicht?

von Florian (Gast)


Lesenswert?

Ich rufe meine Hilfsfunktion nur mit Konstanten als Parameter auf, nicht 
mit Variablen. Der Compiler weiss also bereits zur Compilezeit wie lange 
ich warten will, daher hat es mich etwas gewundert, dass das nicht 
wegoptimiert wird... Danke für die Antworten!

von Falk B. (falk)


Lesenswert?

@ Florian (Gast)

>ich warten will, daher hat es mich etwas gewundert, dass das nicht
>wegoptimiert wird...

Kann er prinzipiell nicht. _delay_ms(ms) kann nicht mal variabel und mal 
fest sein. Geh mal davon aus, dass die Compiler schlauer sind als 90% 
der Programmierer ;-)

MFG
Falk

von Benedikt K. (benedikt)


Lesenswert?

Florian wrote:
> daher hat es mich etwas gewundert, dass das nicht
> wegoptimiert wird...

Dazu müsste der Compiler die Schleife durch mehrfachen Aufruf ersetzen. 
Das macht der nicht so ohne weiteres. Daher wird er die Schleife zu 
Laufzeit berechnen und die delay Funktion entsprechend aufrufen 
(vermutlich mit dem Float Parameter).

von Manni (Gast)


Angehängte Dateien:

Lesenswert?

Ich verwende grundsätzlich die attached Funktionen:

 void delay_us (uint16_t n);
 void delay_ms (uint16_t m);

Diese sind vom Timing nahezu exakt, mit Ausnahme von 5 > n > 1 bei 
delay_us. Speicherplatz nur 26 Bytes.

Gruß Manni

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.