Memory Usage in Data Segment by __clz_tab??

OP (Firma: privat) #734871
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
OP (Firma: privat) #734926
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
OP (Firma: privat) #734990
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
#734995
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);
OP (Firma: privat) #735012
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
Gast #735124
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.
#735180
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.

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