Hallo Leute,
ich bin grad dabei eine möglichst schnelle SPI interrupt routine zu
schreiben und hab mir zu dem Zweck mal das listing (lss) vom avr-gcc
angeguckt. Ich verwende einen ATmega168P. Optimierung -Os
Hier der C-Code:
1
uint8_trxd;
2
uint8_ttxd;
3
4
ISR(SPI_STC_vect)
5
{
6
rxd=SPDR;
7
SPDR=txd;
8
}
und hier das Resultat (ASM + C mix):
1
uint8_trxd;
2
uint8_ttxd;
3
4
ISR(SPI_STC_vect)
5
{
6
90:1f92pushr1
7
92:0f92pushr0
8
94:0fb6inr0,0x3f;63
9
96:0f92pushr0
10
98:1124eorr1,r1
11
9a:8f93pushr24
12
rxd=SPDR;
13
9c:8eb5inr24,0x2e;46
14
9e:80930101sts0x0101,r24
15
SPDR=txd;
16
a2:80910001ldsr24,0x0100
17
a6:8ebdout0x2e,r24;46
18
}
19
a8:8f91popr24
20
aa:0f90popr0
21
ac:0fbeout0x3f,r0;63
22
ae:0f90popr0
23
b0:1f90popr1
24
b2:1895reti
So, Quizfragen:
1. Was wird da mit r1 gemacht? Das ergibt keinen Sinn für mich.
2. Könnte man nicht anstelle von r24 auch r0 verwenden oder umgekehrt.
Das würde dann ein Register weniger machen.
3. Wozu push und pop von r0 bei Adresse 96 und aa?
Mag mich vielleicht jemand erleuchten?
Zu 3. An den Stellen wird SREG gerettet und restauriert.
Grundsätzlich würde ein Register ausreichen. Erzeugen andere
Optimierungsstufen besseren oder schlechteren Code?
Der ISR-Prolog wird auch bei anderen Optimierungen gleich bleiben.
Er ist i.W. statisch, zumindest was zero_reg (R1) und tmp_reg (R0) und
das Sichern von SREG angeht.
Wenn's wirklich auf das letzte Tick ankommt --> (Inline) Assembler
Serieller schrieb:> Zu 3. An den Stellen wird SREG gerettet und restauriert.>> Grundsätzlich würde ein Register ausreichen. Erzeugen andere> Optimierungsstufen besseren oder schlechteren Code?
Bei 94 wird doch SREG in r0 geladen. Bei AC wiederhergestellt.
Dazwischen liegt ein push r0 und pop r0. Ohne das in dem Bereich r0
geändert wird. Das verwundert mich.
Andere Optimierungsstufen bringen wie bereits vermutet keine Änderungen.
Bei Entwicklung des AVR-GCC wurden irrtümlich R0, R1 als Null und
SREG-Sicherung festgelegt.
Sie sind aber verbrannte Register, da einige Befehle sie zerstören (LPM,
SPM, MUL).
Es traut sich aber keiner, das zu korrigieren (z.B. auf R2, R3), daher
ist dieser Overhead bis in alle Ewigkeit drin.
Und auch nach jedem MUL-Befehl muß das Nullregister schnell wieder
gelöscht werden.
Peter
Peter Dannegger schrieb:> Bei Entwicklung des AVR-GCC wurden irrtümlich R0, R1 als Null und> SREG-Sicherung festgelegt.
Das ist kein Irrtum.
> Sie sind aber verbrannte Register, da einige Befehle sie zerstören (LPM,> SPM, MUL).
Wenn tmp_reg anders läge und ein MUL ausgeführt würde, müssten noch mehr
GPRs gesichert werden (R0, R1, R2, R3). Dann wär das Geschrei noch
größer.
> Es traut sich aber keiner, das zu korrigieren (z.B. auf R2, R3), daher> ist dieser Overhead bis in alle Ewigkeit drin.
Wegen 2 push/pop das ABI ändern???
Andre R. schrieb:> Andere Optimierungsstufen bringen wie bereits vermutet keine Änderungen
Das ist keine Vermutung, es steht in den GCC-Quellen.
Johann
Eric B. schrieb:> Johann L. schrieb:>> uint8_t rxd;>> uint8_t txd;>> <korinthen>Fehlt da nicht ein volatile? </korinthen>
Musst du den Autor (TO) fragen. Ansonsten ist es gültiger C-Code, der
die Sachlage ebenso gut demonstriert wie mit volatile.
Bernd schrieb:> Schade. Dann war die Störung der Totenruhe ja völlig umsonst.
Wieso?
Es ist ein Beitrag zum Thema, und wenn ein Suchender die Web-Suche
bemüht, ist es nicht unwahrscheinlich, dass er hier langet.
Bernd schrieb:> Ja. Und wenn er nicht zu den 1% Linux-Kellerkindern gehört, ist er> enttäuscht, weil er die neue Version gar nicht nutzen kann.
Er weiß aber, dass das neue Feature in Arbeit und sogar schon recht weit
fortgeschritten ist, und dass deswegen in absehbarer Zeit ganz sicher
auch ein Binary-Release für Leute ohne Keller verfügbar sein wird.
Auch ich werde jetzt nicht sofort in den Keller gehen und die neue
Version bauen, da ich zur Zeit nichts mit AVRs mache. Trotzdem ist die
Information für mich wertvoll. Denn wenn der Zeitpunkt gekommen ist, wo
ich wieder etwas mit AVRs anfange, weiß ich, dass ich mich erst einmal
nach einem neuen GCC-Release umsehen sollte, das es bis dahin vielleicht
auch als Ready-To-Use-Paket gibt.
Insofern finde ich es super von Johann, dass er uns bzgl. interessanter
Weiterentwicklungen des AVR-GCC auf dem Laufenden hält.
Yalu X. schrieb:> Bernd schrieb:>> Ja. Und wenn er nicht zu den 1% Linux-Kellerkindern gehört, ist er>> enttäuscht, weil er die neue Version gar nicht nutzen kann.
Nach 2 x git pull und jeweils 2 x make install hatte ich unter
/usr/local/avr-git nach ca. 60 min. alles zur Verfügung (die
Arch-Linux-User sollten allerdings in den binutils guile deaktivieren).
Yalu X. schrieb:> Er weiß aber, dass das neue Feature in Arbeit und sogar schon recht weit> fortgeschritten ist,
Was die Quellen angeht, ist das Feature fertig, d.h. upstream in GCC und
Binutils. Extra Patches braucht man also keine.
Die Windows-Kellerkinder bedanken sich! :D
Leider hängt sich der gcc in einem ersten Test beim Kompilieren komplett
auf (100% CPU-Last, bis man abbricht). Ich muss in den nächsten Tagen
mal schauen, ob ich ein Testbeispiel hinkriege. Kann aber etwas dauern.
Bernd schrieb:> Die Windows-Kellerkinder bedanken sich! :D>> Leider hängt sich der gcc in einem ersten Test beim Kompilieren komplett> auf (100% CPU-Last, bis man abbricht). Ich muss in den nächsten Tagen> mal schauen, ob ich ein Testbeispiel hinkriege. Kann aber etwas dauern.
Hängt auch bei mir. :-/ Ich werd die Version wieder offline nehmen.
Ne Windows version zu erstellen ist etwas aufwändig, und richtig testen
kann ich das auch nicht außer auf ner alten Win2000-Nudel. Und den
Compiler Debuggen kann ich auch nicht...
Wegen dem Thread hatte ich gestern auch einmal das Bedürfnis die ganze
Geschichte selbst zu basteln. Bin dann um 2 Uhr auch fast fertig
geworden. Kompillieren konnte ich, allerdings habe ich ein paar Probleme
mit der aktuellen avr-libc.
In meinem Arduino-Ordner (Windows) oder unter /usr/avr...(Ubuntu)
befinden sich in den Ordnern z.B. crtatemga2560.o und libatmega2560.a
Wenn ich jetzt die avr-libc-bin-1.8.1.zip oder die 2.0.0 angucke [*1],
dann befindet sich dort nur eine crtm2560.o
Was mach ich da falsch?
[*1]
https://download.savannah.gnu.org/releases/avr-libc/binary-releases/
Nico W. schrieb:> In meinem Arduino-Ordner (Windows) oder unter /usr/avr...(Ubuntu)> befinden sich in den Ordnern z.B. crtatemga2560.o und libatmega2560.a>> Wenn ich jetzt die avr-libc-bin-1.8.1.zip oder die 2.0.0 angucke [*1],> dann befindet sich dort nur eine crtm2560.o>> Was mach ich da falsch?
Du musst den Compiler zum generieren der AVR-LibC verwenden, der auch in
der zu erstellenden Toolchain verwendet wird.
Also den bereits installierten avr-gcc in den Pfad aufnehmen oder
Johann L. schrieb:> Bernd schrieb:>> Hast du einen Link zu einem Windows-Binary deines gcc v8?
Versuch #2 hochgeladen als "avr-gcc-8.0_2017-07-18_mingw32.zip" in
https://sourceforge.net/projects/mobilechessboar/files/avr-gcc%20snapshots%20%28Win32%29/
Zur Verwendung gilt das gleiche wie oben:
> Einfach das ZIP an einen gewünschten Ort auspacken.>> Verwenden durch absoluten Pfad nach ..../bin/avr-gcc bzw.> ..../bin/avr-gcc-8.0.0 oder Eintragen in Umgebungsvariable PATH.>> Enthält GCC trunk, Binutils master and AVR-LibC trunk +> https://savannah.nongnu.org/patch/?9400>> Passendes Manual dazu: http://gcc.gnu.org/onlinedocs/gcc/
Ich hab versucht einen anderen x86_64-linux-gnu -> mingw32
Cross-Toolchain zu verwenden. Angetestet unter wine schein das Ergebnis
zu funktionieren, mit einem älteren Windos bekomme ich allerdings
Mit -fno-use-linker-plugin oder explizit -fno-lto lässt es sich umgehen.
Warum dieser Fehler auftritt weiß ich nicht, vielleicht ein Problem mit
der asprintf Implementierung von M$; im Endeffekt das gleiche Problem,
das ich schon hier hatte:
Beitrag "Re: AVR-GCC selbst bauen - Unter Linux für Windows?"
Johann L. schrieb:> Also den bereits installierten avr-gcc in den Pfad aufnehmen oder> ../../sources/avr-libc/trunk/configur --host=avr --prefix=$INSTALL_PATH> CC=$INSTALL_PATH/bin/avr-gcc
Perfekt! Danke. Jetzt läuft alles rund.
Vielleicht hab ich gestern Nacht mal zwischendurch das Terminal-Fenster
gewechselt. Eigentlich hatte ich den avr/bin im PATH.
Wie auch immer. Mit CC geht's dann nimmer schief.
Läuft hier jetzt auch, danke. Das Kompilat ist leider gegenüber dem
6.3.1 nochmal um 2% gewachsen. :/
Weil wir beim Thema "overhead" sind: Besteht da eigentlich Interesse,
mal genauer zu erforschen, woran dieses "aus dem Leim" gehen mit jeder
neuen Version genau liegt? Man könnte ja mal ein paar kleine Programme
kompilieren und dann vergleichen.
Mein Programm ist 2% kleiner geworden. Etwas ähnliches konnte ich aber
auch bei dem ersten Einsatz von LTO sehen. Dabei waren die Programme
alle miteinander Verwandt. Dennoch wurde das eine deutlich kleiner
während ein anderes größer wurde.
Für diejenigen, die diesen Fehler auch sehen, hab ich eine neue Version
"avr-gcc-8.0_2017-07-19_mingw32" hochgeladen, die asprintf durch xmalloc
+ sprintf ersetzt.
Bernd schrieb:> Das Kompilat ist leider gegenüber dem 6.3.1 nochmal um 2% gewachsen. :/> Weil wir beim Thema "overhead" sind: Besteht da eigentlich Interesse,> mal genauer zu erforschen, woran dieses "aus dem Leim" gehen mit jeder> neuen Version genau liegt?
Wenn du jemand findest, der sich dafür interessiert...
Das Motto ist ja "wenn man es nicht selbst macht, macht's keiner". So
hab ich z.B. wegen des ISR-Overheads und des GAS-Teils in den avr-gcc
Mailing Listen angefragt, ob jemand den GAS-Teil übernehmen würde.
Natürlich kamen keine Beiträge zum Thema — schon garnicht fand sich ein
jemand oder eine jemandin zum Klöppeln des GAS-Teils — sondern nur Tipps
wie "schreib die ISR in Inline Asm" oder "Instruktionen scannen ist doch
easy".
Im Endeffekt hab ich mich dann dazu entschieden, selbst dieser jemand zu
sein. Und mich in GAS zurechtzufinden und das Zeug runterzuschreiben
war wahrscheinlich weniger Mühl und schneller getan als einem zu
erklären, was man da genau braucht und wie das exakt arbeiten soll und
was nicht funktioniern muss und wo die Haken und Ösen sind usw.
trallala.
Nicht wenige die hier schreiben, haben wahrscheinlich irgendwo ihre
eigene Nerd-Ecke, in der sie gerne basteln: Die einen sind angetreten,
die Physik aus den Angeln zu heben, andere wollen die Welt und den
ganzen Rest auf Hex umstellen, und meine Nerd-Spielwiese ist eben
avr-gcc. Von Assembler bis C++ ist da alles dabei und adäquat, man
kann sich in Testing oder Profiling vertiefen. Wenn ich was im Simulator
praktisch finde, bastel ich daran weiter, und neue
(Optimierungs)-Algorithmen entwerfen und schreiben macht man sonst auch
eher selten.
Dass Leute avr-gcc beruflich einsetzen und mein Gebastel praktisch
finden, oder fluchen wenn ich nen Bug eingebaut hab — ist eben so :-)