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
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
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".
> 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
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.
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
; 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.
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?
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.
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.
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.
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.