mikrocontroller.net

Forum: Compiler & IDEs AVR-GCC generiert unnötigen(?) ISR overhead


Autor: Andre R. (ryan87)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
uint8_t rxd;
uint8_t txd;

ISR(SPI_STC_vect)
{
  rxd = SPDR;
  SPDR = txd;
}

und hier das Resultat (ASM + C mix):
uint8_t rxd;
uint8_t txd;

ISR(SPI_STC_vect)
{
  90:  1f 92         push  r1
  92:  0f 92         push  r0
  94:  0f b6         in  r0, 0x3f  ; 63
  96:  0f 92         push  r0
  98:  11 24         eor  r1, r1
  9a:  8f 93         push  r24
  rxd = SPDR;
  9c:  8e b5         in  r24, 0x2e  ; 46
  9e:  80 93 01 01   sts  0x0101, r24
  SPDR = txd;
  a2:  80 91 00 01   lds  r24, 0x0100
  a6:  8e bd         out  0x2e, r24  ; 46
}
  a8:  8f 91         pop  r24
  aa:  0f 90         pop  r0
  ac:  0f be         out  0x3f, r0  ; 63
  ae:  0f 90         pop  r0
  b0:  1f 90         pop  r1
  b2:  18 95         reti

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?

Autor: Serieller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zu 3. An den Stellen wird SREG gerettet und restauriert.

Grundsätzlich würde ein Register ausreichen. Erzeugen andere 
Optimierungsstufen besseren oder schlechteren Code?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Andre R. (ryan87)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
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

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es wurde ja weiter oben schon geschrieben, wenn es tatsächlich auf diese 
2 Zyklen weniger ankommt, muß man die ISR halt in Assembler schreiben.

Oliver

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder avr-gcc v8 + Binutils 2.29 verwenden:
#include <avr/io.h>
#include <avr/interrupt.h>

uint8_t rxd;
uint8_t txd;

ISR (SPI_STC_vect)
{
  rxd = SPDR;
  SPDR = txd;
}

int main;
$ avr-gcc -mmcu=atmega8 isr.c -Os && avr-objdump -d a.out
00000048 <__vector_10>:
  48:   8f 93           push    r24
  4a:   8f b1           in      r24, 0x0f       ; 15
  4c:   80 93 63 00     sts     0x0063, r24     ; 0x800063 <rxd>
  50:   80 91 62 00     lds     r24, 0x0062     ; 0x800062 <txd>
  54:   8f b9           out     0x0f, r24       ; 15
  56:   8f 91           pop     r24
  58:   18 95           reti

Je nach Dauer von push / pop sind das dann 9 bis 15 Zyklen.

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leichenfledderer. ;))

Hast du einen Link zu einem Windows-Binary deines gcc v8?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd schrieb:
> Leichenfledderer. ;))

Isch weiß.

> Hast du einen Link zu einem Windows-Binary deines gcc v8?

Nö.

Autor: Eric B. (beric)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. schrieb:
> uint8_t rxd;
> uint8_t txd;

<korinthen>Fehlt da nicht ein volatile? </korinthen>

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schade. Dann war die Störung der Totenruhe ja völlig umsonst. Dabei war 
die Lieferzeit schon fast um!

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Äh, Liegezeit. Blöde Autokorrektur.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
3 lesenswert
nicht lesenswert
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.

: Bearbeitet durch User
Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
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.

Autor: Raoul De Souza (raoul_d219)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Bernd schrieb:
> Hast du einen Link zu einem Windows-Binary deines gcc v8?

Eins hochgeladen als "avr-gcc-8.0_2017-07-17_mingw32.zip" in

https://sourceforge.net/projects/mobilechessboar/f...

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/

: Bearbeitet durch User
Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Nico W. (nico_w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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-lib...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Namen in der avr-libc sind abhängig von der Compilerversion.
Sie passen sich an das an, was der Compiler dann sehen will.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
../../sources/avr-libc/trunk/configur --host=avr --prefix=$INSTALL_PATH CC=$INSTALL_PATH/bin/avr-gcc
Bei einem Canadian-Cross Build muss CC= natürlich zum build->target 
compiler zeigen, nicht zum host->target compiler.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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/f...

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
e:/winavr/8.0_2017-07-18/bin/../lib/gcc/avr/8.0.0/../../../../avr/bin/ld.exe: error: asprintf failed

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

Autor: Nico W. (nico_w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Nico W. (nico_w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. schrieb:
> e:/winavr/8.0_2017-07-18/bin/../lib/gcc/avr/8.0.0/../../../../avr/bin/ld.exe: 
> error: asprintf failed

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 :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.