Forum: Compiler & IDEs Memory Usage in Data Segment by __clz_tab??


von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Hallo!!

Leider bin ich alles andere als ein GCC Experte.
Soweit ich verstehe, enthält das Datensegment initialisierte Daten. Also 
z.B. die berühmten Stringkonstanten. Obwohl ich meines Wissens alles 
vermeide, was dort Platz brauchen könnte, werden trotzdem 256 Byte 
belegt.

Auf der Suche habe ich mal einen Blick ins .map File geworfen.

.data          0x00800060        0x0 
/usr/lib/gcc/avr/4.2.1/avr5/libgcc.a(_pac$
 .data          0x00800060      0x100 
/usr/lib/gcc/avr/4.2.1/avr5/libgcc.a(_clz$
                0x00800060                __clz_tab
 .data          0x00800160        0x0 
/usr/lib/gcc/avr/4.2.1/../../../../avr/li$
 .data          0x00800160        0x0 
/usr/lib/gcc/avr/4.2.1/../../../../avr/li$

Ohne wirklich etwas zu verstehen, sieht es so aus, als würde etwas das 
__clz_tab heisst, die 256 Byte verwenden. Aber was ist das?

Vielen Dank!
Klaus

von Frank B. (frank_b) Benutzerseite


Lesenswert?

Siehe hier:

Beitrag "Winavr20071221 :-("

Es ist ein Bug, es gibt aber einen Patch dafür.

Frank

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Frank B_. wrote:
> Siehe hier:
>
> Beitrag "Winavr20071221 :-("
>
> Es ist ein Bug, es gibt aber einen Patch dafür.

Na, das fängt ja schön an :-).

Egal, vielen Dank für den Hinweis!

Wenn ich den Thread aber richtig verstehe, geht es um
eine neue Implementierung der floatingpoint lib.
In meinem Fall sollte die aber gar nicht verwendet werden.

Vermutlich ein Fehler meinerseits. Aber ich verstehe es
trotzdem nicht ganz.

Es lässt sich auf folgende zwei Zeilen reduzieren:


        uint8_t l;
        _delay_ms(l);


bindet die library ein,

       int l;
       _delay_ms(l);

hingegen nicht.

       int l;
       _delay_ms((uint8_t)l);

aber auch nicht.

Ein Blick in avr-libc docu offenbart, dass _delay_ms einen
double Wert erwartet. Dass zur Konvertierung von Integer
in double die math lib benötigt wird mag sein, aber warum
nur bei uint8 und nicht bei int? Liegt das irgendwie am
Vorzeichen?

Viele Grüße!
Klaus

von Andreas K. (a-k)


Lesenswert?

RTFM. Von den Delay-Routinen.

Ja, es liegt auch am Vorzeichen, weil genau darin der im Thread 
beschriebene Bug liegt. Wird aber auch mit Vorzeichen nicht wirklich den 
gewünschten Erfolg haben.

von Frank B. (frank_b) Benutzerseite


Lesenswert?

Ich würde an Deiner Stelle die alte WINAVR-Version (20070525) benutzen, 
die hat den Bug nicht.

Zu dem delay gibts hier irgendwo ein Tutorial, glaube ich.
In Kürze: delay_ms und delay_us immer mit Konstanten aufrufen.

Frank.

von Frank B. (frank_b) Benutzerseite


Lesenswert?


von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Andreas Kaiser wrote:
> RTFM. Von den Delay-Routinen.
>
> Ja, es liegt auch am Vorzeichen, weil genau darin der im Thread
> beschriebene Bug liegt. Wird aber auch mit Vorzeichen nicht wirklich den
> gewünschten Erfolg haben.

Ich denke ich habe das Manual gelesen und gehe davon aus, dass Du darauf 
hinaus willst, dass die Routine nur mit Konstanten aufgerufen werden 
darf, Optimierung usw...
Sollte hier eigentlich der Fall sein:

void sound(int8_t sound, uint8_t len)
{
 while ( len > 0 )
     {
        _delay_ms(sound);
        BUZZER_PORT |= bUZZER;
        _delay_ms(sound);
        BUZZER_PORT &= ~bUZZER;
        len--;
     }
}

Aufruf z.b. mit:
sound(1,4);

Ich ging davon aus, dass der Compiler das alles wegoptimiert.
So wie es jetzt da steht (int8_t statt uint8_t) funktioniert's auch und 
es liegt dann wohl doch an dem beschriebenen Bug.

Viele Grüße
Klaus

von Andreas K. (a-k)


Lesenswert?

Die Delay-Routine muss mit einer Konstanten aufgerufen werden. Was bei 
dir nicht der Fall ist, denn "sound" ist eine Variable (ein Parameter). 
Dass der im aufrufenden Quelltext konstant ist, hilft dir nur dann 
etwas, wenn die Funktion "sound" komplett inlined werden sollte.

Dass der Parameter den gleichen Namen hat wie die Funktion, dient wohl 
in erster Linie der Verwirrung unvorbereiteter Leser?

Und dass es mit "int" besser funktioniert als bei "unsigned" liegt in 
der Tat an dem Bug. Nur wirst du bei genauer Analyse feststellen, dass 
in dem Aufruf von _delay_ms eine Fliesskommarechnung steckt. Die bei dir 
zur Laufzeit durchgeführt wird und somit taktfrequenzabhängig das Delay 
vergrössert. Und zwar egal ob mit oder ohne Vorzeichen, der Unterschied 
liegt nur darin, welche Fliesskommaruntime verwendet wird.

Was du statt dessen machen solltest:
   for (uint8_t i = 0; i < sound; ++i)
      _delay_ms(1);

von Klaus W. (Firma: privat) (texmex)


Lesenswert?

Hallo Andreas!

> Die Delay-Routine muss mit einer Konstanten aufgerufen werden. Was bei
> dir nicht der Fall ist, denn "sound" ist eine Variable (ein Parameter).
> Dass der im aufrufenden Quelltext konstant ist, hilft dir nur dann
> etwas, wenn die Funktion "sound" komplett inlined werden sollte.
bing klar, jetzt hab ich's begriffen!

> Dass der Parameter den gleichen Namen hat wie die Funktion, dient wohl
> in erster Linie der Verwirrung unvorbereiteter Leser?
:-). Ja, genau!

> Und dass es mit "int" besser funktioniert als bei "unsigned" liegt in
> der Tat an dem Bug. Nur wirst du bei genauer Analyse feststellen, dass
> in dem Aufruf von _delay_ms eine Fliesskommarechnung steckt. Die bei dir
> zur Laufzeit durchgeführt wird und somit taktfrequenzabhängig das Delay
> vergrössert. Und zwar egal ob mit oder ohne Vorzeichen, der Unterschied
> liegt nur darin, welche Fliesskommaruntime verwendet wird.
Soweit so klar, aber das heisst bei signed wird die alte, bei unsigned 
die neue (und mit ihr das rätselhafte __clz_tab) eingebunden 
(bugbedingt)?
Die neue routine ist aber auch im .text Segment fast 1kbyte länger dann. 
Ok, da sind vielleicht die 256Byte aus dem Datensegment für die 
Initialisierung dabei?
Na, ok, ich glaube diese Probleme lasse ich erstmal die Experten lösen 
:-).

Danke für die Aufklärung!
Viele Grüße!
Klaus

von Rolf Magnus (Gast)


Lesenswert?

> Ich ging davon aus, dass der Compiler das alles wegoptimiert.

Das tut er auch, aber nur, wenn die Funktion sound immer inline 
expandiert wird. Du kannst das ezwingen, indem du ihr das 
__attribute__((always_inline)) mitgibst. Ohne inlining wird der 
Parameter über ein Register übergeben und kann daher innerhalb der 
Funktion gar keine Compiletime-Konstante sein.

> Die neue routine ist aber auch im .text Segment fast 1kbyte länger
> dann. Ok, da sind vielleicht die 256Byte aus dem Datensegment für die
> Initialisierung dabei?

Ist anzunehmen.

von Andreas K. (a-k)


Lesenswert?

Klaus W. wrote:

> Soweit so klar, aber das heisst bei signed wird die alte, bei unsigned
> die neue (und mit ihr das rätselhafte __clz_tab) eingebunden

Nicht ganz. Es gibt deren drei. Die alte libm/fplib von avr-libc 1.4, 
die neue libm/fplib von 1.6, und irgendwas obskures generisches in der 
libgcc. Letztere ist die mit der clz_tab drin, die erwischt es aber nur, 
wenn irgendwas in der libm/fplib fehlt.

Mit Vorzeichen kriegst du also die neue fplib, ohne Vorzeichen die 
libgcc.

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.