Forum: Compiler & IDEs avr-gcc: Array an 256 Byte ausrichten?


von Sebastian B. (Gast)


Lesenswert?

Moin,

der Betreff sagt's eigentlich schon. Kann ich ein Array in C mit einem 
Alignment von 256 Byte anlegen (im Flash)? Alle Alignments groesser 8 
Byte scheint der Compiler zu ignorieren.

in Assembler gehts ganz einfach mit
1
 .p2alignw 8, 0

Danke,
Sebastian

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Sebastian B. schrieb:
> Moin,
>
> der Betreff sagt's eigentlich schon. Kann ich ein Array in C mit einem
> Alignment von 256 Byte anlegen (im Flash)? Alle Alignments groesser 8
> Byte scheint der Compiler zu ignorieren.

Ja, avr-gcc definiert BIGGEST_ALIGNMENT als 8.

> in Assembler gehts ganz einfach mit
>
>
1
 .p2alignw 8, 0

Du könntest es in eine eigene Section legen und per Linker-Script die 
Section passend alignen.

Alternativ funktioniert vielleicht auch
1
asm (".section  .progmem.data,\"a\",@progbits");
2
asm (".align 8");

auf oberster C-Ebene, direkt vor der Definition des Arrays. Dazu dann 
aber -fno-toplevel-reorder angeben, damit das asm vor der Definition 
verbleibt.

Johann

von Sebastian B. (Gast)


Lesenswert?

Moin,

ich hab mir jetzt mal testweise fuer das Array ne neue Section angelegt:
1
const uint8_t font[8*256] __attribute__ ((section (".bigalign"))) = 
2
{
3
...
4
};

und das ganze per Linker-Flag an eine feste Position gelegt (das 
rumdoktoren am Linker-Script wuerde ich mir gerne ersparen):
1
LDFLAGS +=  [...] -Wl,--section-start=.bigalign=0x2000

Im Map File steht nun das am Ende:
1
.bigalign       0x00002000      0x800
2
 .bigalign      0x00002000      0x800 font.o
3
                0x00002000                font

Ich hab's noch nicht weiter ausprobiert, aber schaut soweit doch erstmal 
gut aus?

Sebastian

von Stefan E. (sternst)


Lesenswert?

Sebastian B. schrieb:

> Ich hab's noch nicht weiter ausprobiert, aber schaut soweit doch erstmal
> gut aus?

Funktioniert (IMO) aber nur so lange, wie der restliche Flashinhalt 
unter der Adresse bleibt, ansonsten gibt es einen "Section 
Overlapping"-Fehler. Der Linker legt das text-Segment nicht um deine 
Section "drumherum".

von Sebastian B. (Gast)


Lesenswert?

> Funktioniert (IMO) aber nur so lange, wie der restliche Flashinhalt
> unter der Adresse bleibt, ansonsten gibt es einen "Section
> Overlapping"-Fehler. Der Linker legt das text-Segment nicht um deine
> Section "drumherum".

Ist bei mir aber kein Problem weil ich in dem 64kB Flash <10kB Programm 
drinhabe (brauche den dicken Controller nur wegen des SRAM).

Das ganze ist jetzt getestet und laeuft. Ich finde es zwar noch nicht 
besonders elegant, werds aber erstmal so lassen :-)

Sebastian

von Henrik H. (Firma: TU Chemnitz) (heha)


Lesenswert?

Zur ursprünglichen Frage: Array an 256-Byte-Adresse ausrichten:

Mit den Mitteln des Compilers sowie (gas-)Assemblers und 
vordefinierten Sections geht das nicht, weil Compiler und Assembler 
relozierbaren Kode/Daten generieren und der Linker alles mit Align:2 
(Byte im Kodesegment) bzw. Align:1 (Byte im Datensegment) zusammenpappt. 
Leider beinhalten die mit avr-gcc gelieferten Linkerskripte keine 
Sections mit diesen häufig wünschenswerten Eigenschaften.

In Assembler geht das nur beim Generieren von absolutem Kode (ohne 
Linker), typischerweise mit avrasm.

Mit dem Compiler bzw. relozierbarem Assembler ist das nur über eine 
eigene Section lösbar, die man beim Linken auf eine geeignete Adresse 
setzen muss.
Dabei ist es egal, ob die Tabelle in Assembler, in C oder via 
Templatemetaprogrammierung in C++ vorliegt; letzteres erlaubt das 
Vorberechnen der Tabelle vom Compiler zur Compilezeit.

Die Lösung mit der Kommandozeile

    -Wl,--section-start=.bigalign=0x2000

ist hölzern (weil an bestimmten AVR gebunden) aber übersichtlich. Die 
Angabe 0x2000 ist dabei gcc-typisch eine Byteadresse.

Es geht auch eleganter über ein zusätzliches Linkerskript:

    -T mylinkerscript.x

mit dem Inhalt

    SECTIONS{.bigalign :{FILL(0xFF). = ALIGN(256);}}INSERT AFTER .text

Damit wird die Section ".bigalign" mit der Ausrichtung 256 an die 
".text"-Section des Standard-Linkerskripts angehängt, und die Lücke 
dazwischen mit 0xFF (statt sonst 0x00) aufgefüllt.
Der Weißraum vor ":" und rund um "=" muss bleiben.

Übrigens, das mit dem Punkt vor Sektionsnamen (".bigalign") ist üblich 
aber nicht notwendig. Man tut damit so, als ob es sich um versteckte 
Verzeichniseinträge handeln würde.

von Klummel (Gast)


Lesenswert?

Rein aus Interesse: Warum brauchst du ein Alingnent von 256Byte?

Bisher hatte ich keine solche Anforderung bzw haben Alingnents von 8 
ausgereicht.

von Klummel (Gast)


Lesenswert?

Ah, vermutlich wegen Flash Segmentierung.

von Peter D. (peda)


Lesenswert?

Klummel schrieb:
> Rein aus Interesse: Warum brauchst du ein Alingnent von 256Byte?

Mikrooptimierung.
Man spart eine 16Bit Addition ein.

von Oliver S. (oliverso)


Lesenswert?

Na ja, man könnte dort Daten ablegen, die man unabhängig vom Programm 
flashen möchte. Da ist so eine Adresse als vielfaches der page size 
schon ganz hilfreich.

Oliver

von Falk B. (falk)


Lesenswert?

Peter D. schrieb:
>> Rein aus Interesse: Warum brauchst du ein Alingnent von 256Byte?
>
> Mikrooptimierung.

Nö.

> Man spart eine 16Bit Addition ein.

Ja.

Der Trick ist in C praktisch nutzlos, in ASM bringt er in EXTREMFÄLLEn 
was.

https://web.archive.org/web/20071213040610/http://www.myplace.nu/avr/minidds/index.htm

https://web.archive.org/web/20071213040615/http://www.myplace.nu/avr/minidds/minidds.asm
1
; main loop
2
;
3
;  r28,r29,r30 is the phase accumulator
4
;    r24,r25,r26 is the adder value determining frequency
5
;
6
;   add value to accumulator
7
;  load byte from current table in ROM
8
;  output byte to port
9
;  repeat 
10
;
11
LOOP1:
12
    add    r28,r24      ; 1
13
    adc    r29,r25      ; 1
14
    adc    r30,r26      ; 1
15
    lpm            ; 3
16
    out    PORTB,r0    ; 1
17
    rjmp  LOOP1      ; 2 => 9 cycles

Z wurde vorher mit der Adresse des Signalmusters gelesen, welches auf 
einer 256 Adresse liegt. Damit ist ZH konstant und man kann nur mit ZL 
durch die Tabelle surfen.

von Klummel (Gast)


Lesenswert?

Falk B. schrieb:
> Der Trick ist in C praktisch nutzlos, in ASM bringt er in EXTREMFÄLLEn was.
>...
>Damit ist ZH konstant und man kann nur mit ZL durch die Tabelle surfen.

Ah, Danke.

Die Frage ist natürlich, wieviel Performancegewinn man dadurch hat.
Was zeigt die Erfahrung?

von Klummel (Gast)


Lesenswert?

Mist ich frag zu schnell, im Beispiel ist es ja gut dargestellt.
Ich würde heutzutage trotzdem eher einen performanteren uC nehmnen.
Die Zeiten, in denen ich PIC Assembler fürs Tuning gehakt habe sind 
irgendwie vorbei.

von Falk B. (falk)


Lesenswert?

Klummel schrieb:
> Mist ich frag zu schnell, im Beispiel ist es ja gut dargestellt.

Ohne den Trick müßßte man bei jedem Durchlauf Z komplett neu laden (2 
Takte) und das Byte als 16 Bit Operation addieren (2 Takte). Also 4 
Takte mehr, wodurch die Schleife von 9 auf 13 Takte anwächst, sprich um 
44%. Da lohnt sich der Trick schon.

von Peter D. (peda)


Lesenswert?

Klummel schrieb:
> Die Frage ist natürlich, wieviel Performancegewinn man dadurch hat.

Diese Mikrooptimierungen bringen nur in ganz speziellen akademischen 
Fällen was, in denen der MC keinerlei andere Tasks ausführen muß.

Es gab z.B. mal Homecomputer, die das FBAS komplett in Software erzeugt 
haben. Dadurch konnte die CPU nichts anderes mehr machen. Die einzige 
Zeit für die eigentlichen Tasks war nur in den Signalpausen für die 
Synchronimpulse. Die Rechenleistung war dadurch grauenhaft niedrig.

von Εrnst B. (ernst)


Lesenswert?

Peter D. schrieb:
> Diese Mikrooptimierungen bringen nur in ganz speziellen akademischen
> Fällen was, in denen der MC keinerlei andere Tasks ausführen muß.

immer wieder gern verlinkt:

https://www.linusakesson.net/scene/craft/

da ist z.B. der Font per .align 8 ausgerichtet.

von Falk B. (falk)


Lesenswert?

Εrnst B. schrieb:
> immer wieder gern verlinkt:
>
> https://www.linusakesson.net/scene/craft/

Oh ja, DAS ist Programmierung auf göttlichem Niveau!!! Unglaublich!

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.