Forum: Compiler & IDEs Unnütze Registersicherungen in ISR


von Raoul D. (raoul_d219)


Lesenswert?

Hallo zusammen,

der folgende Code
1
#include <avr/interrupt.h>
2
3
struct AppFlags {
4
    int expired : 1;
5
} __attribute__((packed));
6
7
int main() {
8
}
9
10
ISR(TIMER0_COMPA_vect) { // warum die push/pop in dieser ISR
11
    volatile struct AppFlags* f = (struct AppFlags*)(0x3e);
12
    f->expired = 1;
13
}

produziert
1
.global __vector_10
2
        .type   __vector_10, @function
3
__vector_10:
4
        push r1  ; 
5
        push r0  ; 
6
        in r0,__SREG__   ; ,
7
        push r0  ; 
8
        clr __zero_reg__         ; 
9
/* prologue: Signal */
10
/* frame size = 0 */
11
/* stack size = 3 */
12
.L__stack_usage = 3
13
        sbi 0x1e,0       ; ,
14
/* epilogue start */
15
        pop r0   ; 
16
        out __SREG__,r0  ; ,
17
        pop r0   ; 
18
        pop r1   ; 
19
        reti
20
        .size   __vector_10, .-__vector_10

mit gcc (-Os oder -O3) für AVR Tiny/Mega.

Die Frage: der Compiler kann erkennen, das es sich hier um ein einzelnes 
Bit in GPIOR0 handelt mit einer I/O-Adresse unterhalb von 0x20 und setzt 
deswegen `sbi` ein. Warum erkennt er nicht, das in diesem Fall der 
normale Prolog/Epilog unnützt ist?

: Verschoben durch Admin
von HildeK (Gast)


Lesenswert?

Ja, das habe ich mich auch schon gefragt.
Wenn du dir sicher bist, dass im 'main' keine Register verwendet werden, 
kannst du mit 'ISR_NAKED' den Pro- und Epilog verhindern, brauchst aber 
am Ende ein 'reti'.

von Raoul D. (raoul_d219)


Lesenswert?

HildeK schrieb:
> Ja, das habe ich mich auch schon gefragt.
> Wenn du dir sicher bist, dass im 'main' keine Register verwendet werden,
> kannst du mit 'ISR_NAKED' den Pro- und Epilog verhindern, brauchst aber
> am Ende ein 'reti'.

Nein, das will ich nicht, denn das ist nicht refaktorierungssicher.

Das sollte der gcc alleine können.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Raoul D. schrieb:
> Warum erkennt er nicht, das in diesem Fall der
> normale Prolog/Epilog unnützt ist?

Weil er er eben nicht erkennt.

Die Erkennung einzubauen bedeutet i.W. den Großteil des avr-Backends neu 
zu schreiben. Das sind zwar nur ca. 30000 Zeilen, bislang hat sich aber 
niemand die Mühe eines Redesigns + Testing gemacht.

von Peter D. (peda)


Lesenswert?

Da der AVR keine Interruptlevel kennt und ein ISR_NOBLOCK einem extrem 
leicht ins Bein schießt, muß man eh immer den längsten Interrupt als 
Worst-Case annehmen. Und dann spielt das bischen Push/Pop in einem 
kurzen Interrupt keine Rolle mehr.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?


von Raoul D. (raoul_d219)


Lesenswert?

Johann L. schrieb:
> Raoul D. schrieb:
>> Warum erkennt er nicht, das in diesem Fall der
>> normale Prolog/Epilog unnützt ist?
>
> Weil er er eben nicht erkennt.

Die Antwort ist klar, aber unbefriedigend ...

von Raoul D. (raoul_d219)


Lesenswert?

Johann L. schrieb:
> https://gcc.gnu.org/PR20296

Ok, dann wird sich wohl leider nichts dran ändern.

Mittlerweile gibt es ja auch ein clang-avr-backend. Vielleicht machts 
der besser.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Raoul D. schrieb:
> Johann L. schrieb:
>> https://gcc.gnu.org/PR20296
>
> Ok, dann wird sich wohl leider nichts dran ändern.

Bislang war es niemandem wichtig genug, das zu ändern.

> Mittlerweile gibt es ja auch ein clang-avr-backend. Vielleicht machts
> der besser.

Ja, nimm halt den.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

...und in avr-gcc kann man auch (Inline) Assembler verwenden, falls es 
wirklich notwendig ist und es sich nicht nur um ein kosmetisches Problem 
handelt:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
ISR (TIMER0_COMPA_vect, ISR_NAKED)
5
{
6
    __asm __volatile ("sbi %i[addr], %[bitno]"
7
                      :
8
                      : [addr] "n" (&GPIOR0), [bitno] "n" (0)
9
                      : "memory");
10
    reti();
11
}

von S. R. (svenska)


Lesenswert?

Johann L. schrieb:
> Bislang war es niemandem wichtig genug, das zu ändern.

Hmm, kann man da nicht nachträglich einen (recht simplen) 
Optimierungslauf einbauen, der die "unnützen" Sicherungen wieder 
entfernt?

von Raoul D. (raoul_d219)


Lesenswert?

Johann L. schrieb:
> ...und in avr-gcc kann man auch (Inline) Assembler verwenden, falls es
> wirklich notwendig ist und es sich nicht nur um ein kosmetisches Problem
> handelt:
>
>
1
#include <avr/io.h>
2
> #include <avr/interrupt.h>
3
> 
4
> ISR (TIMER0_COMPA_vect, ISR_NAKED)
5
> {
6
>     __asm __volatile ("sbi %i[addr], %[bitno]"
7
>                       :
8
>                       : [addr] "n" (&GPIOR0), [bitno] "n" (0)
9
>                       : "memory");
10
>     reti();
11
> }

Das braucht man nicht, denn der Compiler wird für Einzelbits im AVR ABI 
immer nur die sbi Instruktion erzeugen.

von Raoul D. (raoul_d219)


Lesenswert?

S. R. schrieb:
> Johann L. schrieb:
>> Bislang war es niemandem wichtig genug, das zu ändern.
>
> Hmm, kann man da nicht nachträglich einen (recht simplen)
> Optimierungslauf einbauen, der die "unnützen" Sicherungen wieder
> entfernt?

Das denke ich auch.
Das könnte man auch einfach durch ein awk/sed-Script erledigen ... ;-)

von Jack (Gast)


Lesenswert?

Raoul D. schrieb:
> Das könnte man auch einfach durch ein awk/sed-Script erledigen ... ;-)

Wenn schon ein Peephole-Optimizer, dann 
https://gcc.gnu.org/onlinedocs/gccint/define_005fpeephole2.html#define_005fpeephole2

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Raoul D. schrieb:
> Das braucht man nicht, denn der Compiler wird für Einzelbits im AVR ABI
> immer nur die sbi Instruktion erzeugen.

Nein, wird er nicht.  Die Optimierung wird vom insn Combiner ausgeführt, 
und wenn der nicht läuft, gibt's auch kein SBI / CBI.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jack schrieb:
> Raoul D. schrieb:
>> Das könnte man auch einfach durch ein awk/sed-Script erledigen ... ;-)
>
> Wenn schon ein Peephole-Optimizer, dann
> 
https://gcc.gnu.org/onlinedocs/gccint/define_005fpeephole2.html#define_005fpeephole2

Nein, dem steht die notwendige Information nicht zur Verfügung, denn der 
arbeitet nur auf RTL, nicht auf Attributen.  Außerdem läuft 
notice_update_cc nach .peep2.  Schließlich und endlich sind zero_reg und 
tmp_reg fixed und werden auch so verwendet; auch dies ich nicht im RTL 
sichtbar, und auch nicht in Attributen.

: Bearbeitet durch User
von Raoul D. (raoul_d219)


Lesenswert?

Johann L. schrieb:
> Raoul D. schrieb:
>> Das braucht man nicht, denn der Compiler wird für Einzelbits im AVR ABI
>> immer nur die sbi Instruktion erzeugen.
>
> Nein, wird er nicht.  Die Optimierung wird vom insn Combiner ausgeführt,
> und wenn der nicht läuft, gibt's auch kein SBI / CBI.

Also, bei mir funktioniert das zuverlässig mit sbi/cbi. Sowohl bei 
bit-fields als auch bei x |= <single-bit-expression> bzw. ... &= ...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Raoul D. schrieb:
> Johann L. schrieb:
>> Raoul D. schrieb:
>>> Das braucht man nicht, denn der Compiler wird für Einzelbits im AVR ABI
>>> immer nur die sbi Instruktion erzeugen.
>>
>> Nein, wird er nicht.  Die Optimierung wird vom insn Combiner ausgeführt,
>> und wenn der nicht läuft, gibt's auch kein SBI / CBI.
>
> Also, bei mir funktioniert das zuverlässig mit sbi/cbi. Sowohl bei
> bit-fields als auch bei x |= <single-bit-expression> bzw. ... &= ...

"Bei mir" und "immer" sind bissl was anderes.

von Raoul D. (raoul_d219)


Lesenswert?

Johann L. schrieb:
> Raoul D. schrieb:
>> Johann L. schrieb:
>>> Raoul D. schrieb:
>>>> Das braucht man nicht, denn der Compiler wird für Einzelbits im AVR ABI
>>>> immer nur die sbi Instruktion erzeugen.
>>>
>>> Nein, wird er nicht.  Die Optimierung wird vom insn Combiner ausgeführt,
>>> und wenn der nicht läuft, gibt's auch kein SBI / CBI.
>>
>> Also, bei mir funktioniert das zuverlässig mit sbi/cbi. Sowohl bei
>> bit-fields als auch bei x |= <single-bit-expression> bzw. ... &= ...
>
> "Bei mir" und "immer" sind bissl was anderes.

Wo ist die Variante?

Oben steht AVR ABI, avr-gcc (-Os | -O3).

Ok, die Version hatte ich verschwiegen: 7.1 bzw. 8.0

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Selbst da hab ich mit CSE schon anderes gesehe.

Ist aber auch egal, wenn du mit dem von mir vorgeschlagenen Code nix 
anfangen kannst, dann kannst du eben nix damit anfangen...

Beitrag #5039790 wurde von einem Moderator gelöscht.
von Raoul D. (raoul_d219)


Lesenswert?

Johann L. schrieb:
> Selbst da hab ich mit CSE schon anderes gesehe.
>
> Ist aber auch egal, wenn du mit dem von mir vorgeschlagenen Code nix
> anfangen kannst, dann kannst du eben nix damit anfangen...

Doch, damit kann ich etwas anfangen. Nur ist es bei ISR_NAKED genau 
dasselbe, was der C-Compiler tut. Also, was soll ich da Assembler 
schreiben ... Oder hast Du nicht verstanden, was mein Kritikpunkt ist?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Raoul D. schrieb:
> Johann L. schrieb:
>> Selbst da hab ich mit CSE schon anderes gesehe.
>>
>> Ist aber auch egal, wenn du mit dem von mir vorgeschlagenen Code nix
>> anfangen kannst, dann kannst du eben nix damit anfangen...
>
> Doch, damit kann ich etwas anfangen. Nur ist es bei ISR_NAKED genau
> dasselbe, was der C-Compiler tut. Also, was soll ich da Assembler
> schreiben ... Oder hast Du nicht verstanden, was mein Kritikpunkt ist?

Habe ich so verstanden, dass du ein Performace-Problem mit dem vom GCC 
erzeugten ISR-Prolog und -Epilog hast.

Diesen kann man wiederum mit naked umgehen, was wiederum wasserfest nur 
mit Inline-Asm ist.  Wenn es ohne Inline-Asm auch funktioniert ist das 
nett, das Funktionieren strikt aus den GCC-Quellen abzuleiten ist aber 
nochmal was ganz anderes.

von Raoul D. (raoul_d219)


Lesenswert?

Johann L. schrieb:
> Raoul D. schrieb:
>> Johann L. schrieb:
>>> Selbst da hab ich mit CSE schon anderes gesehe.
>>>
>>> Ist aber auch egal, wenn du mit dem von mir vorgeschlagenen Code nix
>>> anfangen kannst, dann kannst du eben nix damit anfangen...
>>
>> Doch, damit kann ich etwas anfangen. Nur ist es bei ISR_NAKED genau
>> dasselbe, was der C-Compiler tut. Also, was soll ich da Assembler
>> schreiben ... Oder hast Du nicht verstanden, was mein Kritikpunkt ist?
>
> Habe ich so verstanden, dass du ein Performace-Problem mit dem vom GCC
> erzeugten ISR-Prolog und -Epilog hast.

Nein, ich habe mich nur gewundert, warum das nicht besser optimiert 
wird.


> Diesen kann man wiederum mit naked umgehen, was wiederum wasserfest nur
> mit Inline-Asm ist.  Wenn es ohne Inline-Asm auch funktioniert ist das
> nett, das Funktionieren strikt aus den GCC-Quellen abzuleiten ist aber
> nochmal was ganz anderes.

Tue ich nicht. Steht hier:

http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr.html

von Axel S. (a-za-z0-9)


Lesenswert?

Raoul D. schrieb:
> Johann L. schrieb:
>> Selbst da hab ich mit CSE schon anderes gesehe.
>>
>> Ist aber auch egal, wenn du mit dem von mir vorgeschlagenen Code nix
>> anfangen kannst, dann kannst du eben nix damit anfangen...
>
> Doch, damit kann ich etwas anfangen. Nur ist es bei ISR_NAKED genau
> dasselbe, was der C-Compiler tut. Also, was soll ich da Assembler
> schreiben ... Oder hast Du nicht verstanden, was mein Kritikpunkt ist?

Ich habe in der Tat nicht verstanden, was dein Problem ist. Der Compiler 
sichert manchmal in einer ISR mehr Register als er müßte. OK. Das ist 
sicher ärgerlich, aber kein Beinbruch. Im Zweifel ist korrekter Code 
wichtiger als schneller Code.

Ich sehe für dich 3 Möglichkeiten:

1. Lebe damit, daß der Compiler ein paar Takte pro ISR-Aufruf 
verschwendet.

2. umgehe das Problem, indem du die Generierung von Prolog/Epilog 
abschaltest bzw. in die eigenen Hände nimmst. Ob du die ISR dazu als 
naked deklarierst, oder gleich ganz in (Inline) Assembler schreibst, 
ist Geschmackssache.

3. Such dir einen anderen Compiler, der das besser macht.

Da wir deine Rahmenbedingungen nicht kennen, können wir diese Wahl nicht 
für dich treffen. Aber anscheinend stört dich 1. dermaßen, daß du extra 
deswegen einen Thread aufgemacht hast. 2. hast du weiter oben ohne 
Angabe einer verständlichen Begründung verworfen. Ob 3. überhaupt 
existiert entzieht sich meiner Kenntnis.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

1
#include <avr/io.h>
2
3
void regs (void)
4
{
5
    PINB |= 0x7f;
6
    PINC |= 0x7f;
7
    PIND |= 0x7f;
8
}

von Raoul D. (raoul_d219)


Lesenswert?

Axel S. schrieb:

> Da wir deine Rahmenbedingungen nicht kennen, können wir diese Wahl nicht
> für dich treffen. Aber anscheinend stört dich 1. dermaßen, daß du extra
> deswegen einen Thread aufgemacht hast.

Stimmt nicht, es war eine Frage nach dem warum.

> 2. hast du weiter oben ohne
> Angabe einer verständlichen Begründung verworfen.

Stimmt auch nicht. Lies weiter oben.

Ob 3. überhaupt
> existiert entzieht sich meiner Kenntnis.

clang-avr

von Raoul D. (raoul_d219)


Lesenswert?

Johann L. schrieb:
>
1
> #include <avr/io.h>
2
> 
3
> void regs (void)
4
> {
5
>     PINB |= 0x7f;
6
>     PINC |= 0x7f;
7
>     PIND |= 0x7f;
8
> }
9
>

single-bit???

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ich sollte so spät nix mehr schreiben...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Axel S. schrieb:
> Ich sehe für dich 3 Möglichkeiten:
>
> 1. Lebe damit, daß der Compiler ein paar Takte pro ISR-Aufruf
> verschwendet.
>
> 2. umgehe das Problem, indem du die Generierung von Prolog/Epilog
> abschaltest bzw. in die eigenen Hände nimmst. Ob du die ISR dazu als
> naked deklarierst, oder gleich ganz in (Inline) Assembler schreibst, ist
> Geschmackssache.
>
> 3. Such dir einen anderen Compiler, der das besser macht.

4. Pack den gcc-Source und behebe das Problem.

von Thomas E. (thomase)


Lesenswert?

Warum wird wegen einer simplen Frage nach dem Warum für irgendeinen 
Sachverhalt, dem TO unterstellt, er hätte ein Problem? Und dieses soll 
er gefälligst selbst lösen. So, wie ich seine Aussagen verstanden habe, 
hat er damit überhaupt kein Problem, sondern ist nur neugierig. Manchmal 
ist dieses Forum echt z.K..

von Carl D. (jcw2)


Lesenswert?

Warum gibt es eigentlich überhaupt ein Problem mit 
Einbefehls-Interrupthandlern?
Warum wird nicht einfach das Bit OCF0A im Register TIFR0 abgefragt.

Richtige Interrupts, die auch was sinnvolles tun, brauchen mehr als 0 
Register und verbiegen mit Sicherheit auch Flags. Dann löst sich dieses 
"Problem" in Luft auf und genau deshalb will keiner das Avr-Backend 
umbauen. Wegen einem real nicht existierenden Problem. Bestimmt Gäste 
werden nun besser nach den Blutdrucktabletten greifen. Ändert aber nix.

von avr (Gast)


Lesenswert?

Carl D. schrieb:
> Richtige Interrupts, die auch was sinnvolles tun, brauchen mehr als 0
> Register und verbiegen mit Sicherheit auch Flags.

Bei Avrs ist es durchaus möglich Interrupts zu schreiben, die die Flags 
nicht ändern. Ein FIFO kann beispielsweise so realisiert werden. Dabei 
spielt besonders die "cpse"-Instruktion eine Rolle, mit der Vergleiche 
durchgeführt werden können, ohne die Flags zu ändern (so schlau ist der 
avrgcc allerdings bei Weitem nicht, um solche Interrupts zu generieren).

von Carl D. (jcw2)


Lesenswert?

avr schrieb:
> Carl D. schrieb:
>> Richtige Interrupts, die auch was sinnvolles tun, brauchen mehr als 0
>> Register und verbiegen mit Sicherheit auch Flags.
>
> Bei Avrs ist es durchaus möglich Interrupts zu schreiben, die die Flags
> nicht ändern. Ein FIFO kann beispielsweise so realisiert werden. Dabei
> spielt besonders die "cpse"-Instruktion eine Rolle, mit der Vergleiche
> durchgeführt werden können, ohne die Flags zu ändern (so schlau ist der
> avrgcc allerdings bei Weitem nicht, um solche Interrupts zu generieren).

Ja, aber dann schreibt an sein Programm oder zumindest die ISR in 
Assembler.

Mir persönlich reicht die normale Schläue des GCC völlig und alle, denen 
sie nicht reicht, steht die GCC-Source zur Verfügung. Nur dazu braucht 
es mehr als nur Takte zählen zu können.

von Peter D. (peda)


Lesenswert?

Was nützt es, wenn ein Interrupt sauschnell ist, er aber andere nicht 
unterbrechen kann.
Ich hab mal ein C51-Programm geerbt, wo der Lautsprecher einen 
grauenhaftes Schnarren von sich gab, weil er in SW getoggelt wurde und 
durch andere Interrupts pausieren mußte. Ich hab dann dessen Priorität 
erhöht und schon war der Ton glasklar.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Ich hab mal ein C51-Programm geerbt

Peter, du kannst deinen 8051 doch gern hinterher trauern.  Es wird
nicht viel helfen: entweder nimm sie, oder lebe mit den AVRs, oder
geh' auf einen Cortex-M, da hast du auch wieder Interruptprioritäten.

Wirklich benötigt habe ich sie dort aber bislang auch noch nicht.

Back to topic: habe mir auch noch nicht angesehen, wie der Compiler
bei den Cortexen das handhabt und ob der ISR-Prolog dort feiner
granuliert ist.  Beim AVR kommt ja beim ISR-Prolog die
Designentscheidung dazu, r0 und r1 für tempreg und zeroreg zu nehmen,
die sich nachträglich dann als etwas unglücklich herausgestellt hat.
Die stammt wohl noch aus Zeiten, als es nur einen AT90S1200 und einen
ATmega103 gab, die noch nicht multiplizieren konnten.

: Bearbeitet durch Moderator
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Raoul D. schrieb:
> Johann L. schrieb:
>> Habe ich so verstanden, dass du ein Performace-Problem mit dem vom GCC
>> erzeugten ISR-Prolog und -Epilog hast.
>
> Nein, ich habe mich nur gewundert, warum das nicht besser optimiert
> wird.

Wenn du konkrete Fragen zum AVR-backend des GCC hast oder zum GCC selbst 
so kann ich versuchen, diese zu beantworten.

Ansonsten gilt immer noch folgendes, was u.a. der Grund dafür ist, dass 
eine entsprechende Änderung weder einfach noch lokal wäre:

Johann L. schrieb:
> Jack schrieb:
>> Wenn schon ein Peephole-Optimizer, dann
>
> Nein, dem steht die notwendige Information nicht zur Verfügung, denn
> der arbeitet nur auf RTL, nicht auf Attributen.  Außerdem läuft
> notice_update_cc nach .peep2.  Schließlich und endlich sind zero_reg
> und tmp_reg fixed und werden auch so verwendet; auch dies ich nicht
> im RTL sichtbar, und auch nicht in Attributen.

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Thomas E. schrieb:
> Warum wird wegen einer simplen Frage nach dem Warum für irgendeinen
> Sachverhalt, dem TO unterstellt, er hätte ein Problem?

Weil er nach der schon ganz weit oben vollumfänglich erschöpfenden 
Antwort ("ist halt so") im noch weiter rumquengelt?

Ja, der gcc ist da nicht perfekt, ja, das Leben ist nicht fair, ja, der 
Ponyhof ist abgebrannt, aber es ist halt so, wie es ist.

Oliver

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Jörg W. schrieb:
> habe mir auch noch nicht angesehen, wie der Compiler
> bei den Cortexen das handhabt und ob der ISR-Prolog dort feiner
> granuliert ist.

Einen ISR-spezifischen Prolog/Epilog gibt es nicht. ISRs sind ganz 
gewöhnliche Funktionen. Alles, was im ABI nicht von einer Funktion 
selbst gesichert wird, das wird bereits von der Hardware gesichert. Der 
Return-Befehl erkennt an einer Pseudo-Adresse, dass er mehr zu tun hat 
als sonst.

In den GCC Teil für die Erzeugung des üblichen Prolog/Epilog Codes bei 
ARM hatte ich vor ein paar Jahren allerdings mal reingesehen. 
Grauenhaft. Da hat sich über Jahrzehnte einiges angesammelt und 
erkennbar hat sich kaum jemand an den Code des Vorgängers heran getraut.

: Bearbeitet durch User
von Raoul D. (raoul_d219)


Lesenswert?

Oliver S. schrieb:
> Thomas E. schrieb:
>> Warum wird wegen einer simplen Frage nach dem Warum für irgendeinen
>> Sachverhalt, dem TO unterstellt, er hätte ein Problem?
>
> Weil er nach der schon ganz weit oben vollumfänglich erschöpfenden
> Antwort ("ist halt so") im noch weiter rumquengelt?

Quatsch: mein Kommentar dazu war (s.o.):

> Die Antwort ist klar, aber unbefriedigend ...

Der Rest der Diskussion ging um hauptsächlich andere Dinge!

von Oliver S. (oliverso)


Lesenswert?

Raoul D. schrieb:
> Quatsch: mein Kommentar dazu war (s.o.):
>
>> Die Antwort ist klar, aber unbefriedigend ...

Q.e.d.

Oliver

von Walter S. (avatar)


Lesenswert?

avr schrieb:
> Ein FIFO kann beispielsweise so realisiert werden.

da muss ja auch immer ein Index erhöht werden, wie geht das ohne Flags 
zu ändern?

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Walter S. schrieb:
> avr schrieb:
>> Ein FIFO kann beispielsweise so realisiert werden.
>
> da muss ja auch immer ein Index erhöht werden, wie geht das ohne Flags
> zu ändern?

Hallo,

genau dazu habe ich einen Beitrag aufgemacht, weil es mich auch 
interessiert :-)

Siehe Beitrag "AVR-ISR Assembler ohne Flags zu benutzen"

N.G.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Frank M. schrieb:
> 4. Pack den gcc-Source und behebe das Problem.

Am einfachsten und am ehesten Aussicht auf Umsetzung hätte folgender 
Ansatz:

avr-gcc gibt im ISR Prolog / Epilog Pseudo-Instruktionen aus:
1
__vector_10:
2
        .maybe_push_tmp_reg
3
        .maybe_push_zero_reg
4
        .maybe_push_sreg
5
        .maybe_clear_zero_reg
6
        ;; Rest des Prologs
7
    ;; Code
8
        ;; Rest des Epilogs
9
        .maybe_pop_sreg
10
        .maybe_pop_zero_reg
11
        .maybe_pop_tmp_reg
12
        reti

GAS scannt den Code auf Verwendung von zero_reg, tmp_reg, sreg und gibt 
für die Pseudofunktionen entsprechenden Code aus.

Die Änderung im GCC reduziert sich dann auf einen configure-Test um zu 
untersuchen, ob Binutils das unterstützen, eine neue Option zur 
(De)aktivierung und die Ausgabe der Direktiven in non-naked ISR Prolog + 
Epilog.

Die Änderung im GAS wäre eine neue Option, Dokumentation und 
Implementation der Direktiven, sowie einen Analyse-Pass zu schreiben.

Allerdings weiß ich nicht, wie GAS arbeitet und ob es überhaupt ein 
Multi-Pass Assembler ist, der es einem Backend erlaubt, auf einfache 
Weise (so wie im GCC) neue Passes hinzuzufügen.

Der Ansatz ist recht Hausbacken und nicht die "reine Lehre", aber im 
Vergleich zu GCC-only Lösungen um Größenordnungen einfacher, besser zu 
testen und robuster.

Wenn es jemand gibt, der den GAS-Teil macht, könnte man des recht fix 
umsetzen.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ich hab's mal in der avr-gcc ML aufs Tablett gebracht; wer sich dafür 
interessiert kann sich ja dort einklinken.

https://lists.nongnu.org/mailman/listinfo/avr-gcc-list

von Carl D. (jcw2)


Lesenswert?

Johann L. schrieb:
1
.global __vector_10
2
        .type   __vector_10, @function
3
__vector_10:
4
        push r1  ; 
5
        push r0  ; 
6
        in r0,__SREG__   ; ,
7
        push r0  ; 
8
        clr __zero_reg__         ; 
9
/* prologue: Signal */
10
/* frame size = 0 */
11
/* stack size = 3 */
12
.L__stack_usage = 3
13
        sbi 0x1e,0       ; ,
14
/* epilogue start */
15
        pop r0   ; 
16
        out __SREG__,r0  ; ,
17
        pop r0   ; 
18
        pop r1   ; 
19
        reti
20
        .size   __vector_10, .-__vector_10
>
> GAS scannt den Code auf Verwendung von zero_reg, tmp_reg, sreg und gibt
> für die Pseudofunktionen entsprechenden Code aus.

Der Ansatz würde aber nicht mit LTO zusammenspielen, oder?

> Der Ansatz ist recht Hausbacken und nicht die "reine Lehre", aber im
> Vergleich zu GCC-only Lösungen um Größenordnungen einfacher, besser zu
> testen und robuster.

Man könnte mit weniger Aufwand den avr-as mit einer Schell Versehen, die 
eine ISR und deren Prolog/Epilog erkennt, den "Payload" untersucht und 
gegebenenfalls Prolog/Epilog kürzt. Quasi ein Filter. Da hat man nur 
eine Baustelle.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Carl D. schrieb:
> Johann L. schrieb:
>> GAS scannt den Code auf Verwendung von zero_reg, tmp_reg, sreg und gibt
>> für die Pseudofunktionen entsprechenden Code aus.
>
> Der Ansatz würde aber nicht mit LTO zusammenspielen, oder?

Doch, kein Problem.  Das alles geschieht erst nach LTO-Streaming.

>> Der Ansatz ist recht Hausbacken und nicht die "reine Lehre", aber im
>> Vergleich zu GCC-only Lösungen um Größenordnungen einfacher, besser zu
>> testen und robuster.
>
> Man könnte mit weniger Aufwand den avr-as mit einer Schell Versehen, die
> eine ISR und deren Prolog/Epilog erkennt,

Hängt davon ab, ob jemand GAS anfassen will.  Leute die gut 
programmieren können gibt's ja genug hier, aber keine, die die Tools 
anfassen mögen.

Außerdem weiß ich nicht, wie gut GAS mit interleaved Sections zurecht 
käme wie sie bei Dispatch-Tables (swtich / case) auftauchen.  Zudem 
arbeitet GAS auf section-Ebene soviel ich weiß, nicht auf 
Funktionsebene.  Bei Code wie
1
   isr-prolog
2
   if X
3
      goto L1
4
   isr-epilog
5
   if Y
6
      goto L2
7
L3:
8
   isr-epilog
9
L2:
10
   some-code
11
   goto L3
muss  man erst mal das Funktionsende finden.  Nach dem Parsen hat man 
nur noch elf-Sections mit Relocs.

Ist aber ziemlich hypotetisch das ganze solange sich niemand finded, um 
was auch immer in GAS zu klöppeln.

Blöd wäre auch, implizites Wissen über GCC ISR-Prologe in GAS 
einzubauen.  Wenn ein Epilog dann anders wäre würd man ihn nicht mehr 
erkennen.  Außerdem weiß GAS nicht, ob der Code vom GCC kommt oder von 
einem Asm-Programm, was zu Fehler führen könnte wenn ein Epilog anders 
aussieht und nicht erkannt wird.  Und im GCC will man mindestens eine 
Option haben um das zu steuern, weil kaum jemand -Wa,-foo setzen wird.

von Raoul D. (raoul_d219)


Lesenswert?

Carl D. schrieb:

> Man könnte mit weniger Aufwand den avr-as mit einer Schell Versehen, die
> eine ISR und deren Prolog/Epilog erkennt, den "Payload" untersucht und
> gegebenenfalls Prolog/Epilog kürzt. Quasi ein Filter. Da hat man nur
> eine Baustelle.

Das hatte ich oben schon vorgeschlagen und auch so mittlerweile 
umgesetzt. Ist Bestandteil eines Source-Code-Formatters, den ich schon 
hatte ;-) War ne Sache von 1 Stunde ...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Raoul D. schrieb:
> Carl D. schrieb:
>
>> Man könnte mit weniger Aufwand den avr-as mit einer Schell Versehen, die
>> eine ISR und deren Prolog/Epilog erkennt, den "Payload" untersucht und
>> gegebenenfalls Prolog/Epilog kürzt. Quasi ein Filter. Da hat man nur
>> eine Baustelle.
>
> Das hatte ich oben schon vorgeschlagen und auch so mittlerweile
> umgesetzt. Ist Bestandteil eines Source-Code-Formatters, den ich schon
> hatte ;-) War ne Sache von 1 Stunde ...

Ah, schön.  Dann braucht man an den Tools nix mehr zu optimieren. 
Wenn's ein einfaches sed, awk oder python sctipt viel einfacher erledigt 
:-)

von Carl D. (jcw2)


Lesenswert?

Johann L. schrieb:
>
> Hängt davon ab, ob jemand GAS anfassen will.  Leute die gut
> programmieren können gibt's ja genug hier, aber keine, die die Tools
> anfassen mögen.

Ich hatte mal GAS Source und Doku überflogen und hatte nicht den 
Eindruck, als ob der sich einfach dazu überreden liese.

> Außerdem weiß ich nicht, wie gut GAS mit interleaved Sections zurecht
> käme wie sie bei Dispatch-Tables (swtich / case) auftauchen.  Zudem
> arbeitet GAS auf section-Ebene soviel ich weiß, nicht auf
> Funktionsebene.  Bei Code wie
>
1
>    isr-prolog
2
>    if X
3
>       goto L1
4
>    isr-epilog
5
>    if Y
6
>       goto L2
7
> L3:
8
>    isr-epilog
9
> L2:
10
>    some-code
11
>    goto L3
12
>
> muss  man erst mal das Funktionsende finden.  Nach dem Parsen hat man
> nur noch elf-Sections mit Relocs.

Komplexen Code muß man Dan auch nicht erkennen können, denn nur wirklich 
Simples kann auch verkürzt werden.
Konkret in deinem Beispiel: ich würde nur ganz wenige Befehle zulassen, 
ISRs, die Sprünge aus Prolog/Epilog heraus machen, sind sicher zu 
komplex, die Sprünge sind dann in der Regel bedingt, benutzen also 
Flags.

> Ist aber ziemlich hypotetisch das ganze solange sich niemand finded, um
> was auch immer in GAS zu klöppeln.
>
> Blöd wäre auch, implizites Wissen über GCC ISR-Prologe in GAS
> einzubauen.  Wenn ein Epilog dann anders wäre würd man ihn nicht mehr
> erkennen.  Außerdem weiß GAS nicht, ob der Code vom GCC kommt oder von
> einem Asm-Programm, was zu Fehler führen könnte wenn ein Epilog anders
> aussieht und nicht erkannt wird.  Und im GCC will man mindestens eine
> Option haben um das zu steuern, weil kaum jemand -Wa,-foo setzen wird.

Ja, das entfällt alles mit dem Filter-Lösung.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Carl D. schrieb:
> Johann L. schrieb:
>>
>> Hängt davon ab, ob jemand GAS anfassen will.  Leute die gut
>> programmieren können gibt's ja genug hier, aber keine, die die Tools
>> anfassen mögen.
>
> Ich hatte mal GAS Source und Doku überflogen

Ok.

> Komplexen Code muß man Dan auch nicht erkennen können,

Man muss zunächt mal erkennen, dass der Code simpel ist :-)  Und wie 
du beim Lesen von GAS bereits bemerkt hast, geht es nicht darum, 
irgendwelche Instruktionen zu scannen (macht jeder hier im Schlaf), 
sondern erstmal dahin zu kommen, die Informationen die man dazu braucht 
zusammenzutragen.

> Konkret in deinem Beispiel: ich würde nur ganz wenige Befehle
> zulassen, ISRs, die Sprünge aus Prolog/Epilog heraus machen,

Es sind nicht Sprünge auf dem Prolog raus, sondern im normalen C-Code.

> sind sicher zu komplex, die Sprünge sind dann in der Regel
> bedingt, benutzen also Flags.

Zum einen erzeugt auch der Compiler CPSE, zum anderen geht's nicht nur 
um Flags sondern auch um tmp_reg und zero_reg die evtl. unnötig 
gesichert werden.  Wenn z.B. tmp_reg nicht gebraucht wird aber zero-reg 
(und damit SREG) kann man auch 2 Befehle sparen.

> Ja, das entfällt alles mit dem Filter-Lösung.

Was immer dieses Filter ist... wann und wo konkret wird da wonach 
"gefiltert"?

: Bearbeitet durch User
von Carl D. (jcw2)


Lesenswert?

Johann L. schrieb:
> Man muss zunächt mal erkennen, dass der Code simpel ist :-)  Und wie
> du beim Lesen von GAS bereits bemerkt hast, geht es nicht darum,
> irgendwelche Instruktionen zu scannen (macht jeder hier im Schlaf),
> sondern erstmal dahin zu kommen, die Informationen die man dazu braucht
> zusammenzutragen

So beginnt Isr10:
1
.global __vector_10
2
        .type   __vector_10, @function
3
__vector_10:

So beginnt der Prolog, mit Save r1, r0, _SREG_
1
        push r1  ; 
2
        push r0  ; 
3
        in r0,__SREG__   ; ,
4
        push r0  ; 
5
        clr __zero_reg__         ;

Es erfolgt ein Save zusätzlicher Register (hier keine zusätzlichen)

So endet der Prolog:
1
*/* prologue: Signal */


Der eigentliche Code, der hier weder r0 noch r1 noch die Flags benutzt.
Die Untersuchung kann beliebig kompliziert sein, oder halt sehr simple, 
wenn man nur einfachste Fälle, wie hier, erschlagen muß.
1
/* frame size = 0 */
2
/* stack size = 3 */
3
.L__stack_usage = 3
4
        sbi 0x1e,0       ; ,[pre]
5
6
7
So beginnt der Epilog:
8
[pre]/* epilogue start */

Es erfolgt ein Restore zusätzlicher Register (hier keine zusätzlichen)

So endet der Epilog, mit Restore _SREG_, r0, r1
1
        pop r0   ; 
2
        out __SREG__,r0  ; ,
3
        pop r0   ; 
4
        pop r1   ;
5
        reti

Prolog/Epilog beginnen/enden aktuell fix so.
Falls mehr Register gesichert werden, kann man diese auch analysieren, 
oder einfach nichts tun, weil zu komplex.
Klar sind diese Patter nicht fix, aber da das AVR-Backend ja so 
änderungsfreudig ist ...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Carl D. schrieb:
> Johann L. schrieb:
>> Und wie du beim Lesen von GAS bereits bemerkt hast, geht es nicht
>> darum, irgendwelche Instruktionen zu scannen (macht jeder hier im
>> Schlaf), sondern erstmal dahin zu kommen, die Informationen die man
>> dazu braucht zusammenzutragen
>
> So beginnt ...

Das ist ja alles trivial, aber WO in den Tools willst du das einbauen?

Das Zeug liegt auch nicht als Text vor, im Compiler nicht und in GAS 
auch nicht.  Die Teile im GAS die auf Text arbeiten, die sehen einzelne 
Zeilen und parsen die, ob überhaupt globale Info verfügbar ist weiß ich 
nicht.

> aber da das AVR-Backend ja so änderungsfreudig ist ...

Würd ich so nicht sagen.  Manche Änderungen sind nicht auf das Beckend 
beschränkt oder sind inadäquat viel Aufwand im Vergleich zum Nutzen (wie 
hier).  Insbesonders wie bei kleinen ISRs wie hier wo es auf jeden Tick 
ankommt in einer Applikation ist das Mittel der Wahl Inline-Assembler 
(oder hausbackene Hacks der Anwender nach Gusto).

Dem AVR-backend selbst würde ich auch keine Änderungsfreudigkeit 
zuschreiben, sondern bestenfalls ein Mangel an Entwicklern konstatieren.

Wenn du Änderungen im AVR-Teil hast wirst du ziemlich sicher kein 
Problem haben das durchs Review zu bekommen.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

...und Änderungen gibt es durchaus.  Die letzte Änderung im GCC ist 3 
Tage her und war auch nicht ganz winzig (PR81072): 
http://gcc.gnu.org/r249124

http://gcc.gnu.org/PR81075 ist im Review, vor 3 Wochen: 
http://gcc.gnu.org/r248332

In Binutils kamen in den letzten 3 Wochen PR21583, PR21569 und PR21472 
hinzu, alles Features und keine Bugfixes.

AVR-Libc vermeldet in der letzten Woche allein 5 Commits, z.B: etwas 
mehr avrtiny:

http://svn.savannah.nongnu.org/viewvc/avr-libc?view=revision&revision=2542

Nur dass normale Anwender sich für solche Änderungen nicht interessieren 
bedeutet noch lange nicht, dass sich da nix weiterentwickelt.

von (prx) A. K. (prx)


Lesenswert?

Johann L. schrieb:
> ...und Änderungen gibt es durchaus.  Die letzte Änderung im GCC ist 3
> Tage her und war auch nicht ganz winzig (PR81072):
> http://gcc.gnu.org/r249124

Lockere 10 Jahre zu spät, würde ich sagen. Nicht der GCC, sondern die 
Hardware, auf die das gemünzt ist.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

A. K. schrieb:

> Lockere 10 Jahre zu spät, würde ich sagen. Nicht der GCC, sondern die
> Hardware, auf die das gemünzt ist.

Scheinbar nicht:

Beitrag "Neue 8-Bit Tinys vorgestellt: 417/814/816/817"

von (prx) A. K. (prx)


Lesenswert?

Konkreter: Spätestens mit den AVRX wäre die Flash-Einblendung fällig 
gewesen. Da das nicht kam, waren die für mich gestorben. Jetzt ist das 
in meinen Augen etwas spät. Mussten die erst von Microchip übernommen 
werden, um auf diese Idee zu kommen (die dsPIC30 hatten das auch), oder 
war das von denen patentiert und konnte erst jetzt implementiert werden?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

A. K. schrieb:
> Spätestens mit den AVRX wäre die Flash-Einblendung fällig gewesen.

Soviel ich weiß waren die ersten AVRs mit dem Feature die reduced Tiny, 
also die mit 16 GPRs wie ATtiny40 oder ATtiny4.  Macht aber wohl nicht 
wirklich Spaß die zu programmieren, und "durchgestartet" sind die auch 
nie, obwohl ein ATtiny40 mehr RAM und Flash hat als ein ATtiny2313.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

A. K. schrieb:
> Konkreter: Spätestens mit den AVRX wäre die Flash-Einblendung fällig
> gewesen.

Für größere Devices finde ich das in einem 16-bit-Adressraum eher
unpraktisch.  (Im Grunde finde ich die ganze Flash-Bankerei bei
Devices > 128 KiB unpraktisch, da ist ein 32-bit-Adressraum einfach
sinnvoller.) Die (neuen) Tinys haben in dieser Hinsicht natürlich den
Vorteil, dass dort keiner mehr an so große Gesamtspeichermengen denkt,
sodass alles in 16 Bit Adressraum reinpasst.

von (prx) A. K. (prx)


Lesenswert?

Jörg W. schrieb:
> Für größere Devices finde ich das in einem 16-bit-Adressraum eher
> unpraktisch.

Für grössere Aufgaben fand ich einen 16-Bit Adressraum von Anfang an 
unpraktisch. Und orientierte mich bei passender Gelegenheit lieber an 
ARM (anfangs LPC2000). Und die umständliche Flash/RAM-Pointer 
Unterscheidung hat mit ebenfalls stets genervt.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Frank M. schrieb:
> Axel S. schrieb:
>> 3. Such dir einen anderen Compiler, der das besser macht.
>
> 4. Pack den gcc-Source und behebe das Problem.

Wer's antesten will: avr-gcc v8 (trunk) + Binutils 2.29

Beispiel für den Code von oben:
1
#include <avr/interrupt.h>
2
3
struct AppFlags
4
{
5
    int expired : 1;
6
} __attribute__((__packed__));
7
8
ISR (TIMER0_COMPA_vect)
9
{
10
    volatile struct AppFlags* f = (struct AppFlags*) &GPIOR0;
11
    f->expired = 1;
12
}
13
14
int main;
1
avr-gcc-8 -mmcu=atmega88 isr.c -Os && avr-objdump -d a.out
1
00000056 <__vector_14>:
2
  56:   f0 9a           sbi     0x1e, 0 ; 30
3
  58:   18 95           reti

von Raoul D. (raoul_d219)


Lesenswert?

Na prima. Dann werde ich das bei Gelegenheit mal verifizieren, und wenn 
es ok ist, mein Optimierungsskript wieder entsorgen ;-)

(s.a. Beitrag "AVR-GCC generiert unnötigen(?) ISR overhead")

von Raoul D. (raoul_d219)


Lesenswert?

Raoul D. schrieb:
> Na prima. Dann werde ich das bei Gelegenheit mal verifizieren, und wenn
> es ok ist, mein Optimierungsskript wieder entsorgen ;-)
>
> (s.a. Beitrag "AVR-GCC generiert unnötigen(?) ISR overhead")

Mmh, wohl etwas zu früh gefreut ...

Zwar ist mit dem gcc/g++-8 nun dieses "Problem" beseitigt, jedoch sind 
die enstehenden Codegrößen insgesamt teilweise "wesentlich" größer als 
beim gcc-7.1.1. Was natürlich mindestens einmal den Spareffekt in den 
ISRs dieser speziellen Form insgesamt wieder zunichte macht ...

Genauer untersucht habe ich das (noch) nicht, mir ist es nur beim 
Übersetzen einiger Test-Programme aufgefallen.

von Carl D. (jcw2)


Lesenswert?

Raoul D. schrieb:
> Raoul D. schrieb:
>> Na prima. Dann werde ich das bei Gelegenheit mal verifizieren, und wenn
>> es ok ist, mein Optimierungsskript wieder entsorgen ;-)
>>
>> (s.a. Beitrag "AVR-GCC generiert unnötigen(?) ISR overhead")
>
> Mmh, wohl etwas zu früh gefreut ...
>
> Zwar ist mit dem gcc/g++-8 nun dieses "Problem" beseitigt, jedoch sind
> die enstehenden Codegrößen insgesamt teilweise "wesentlich" größer als
> beim gcc-7.1.1. Was natürlich mindestens einmal den Spareffekt in den
> ISRs dieser speziellen Form insgesamt wieder zunichte macht ...
>
> Genauer untersucht habe ich das (noch) nicht, mir ist es nur beim
> Übersetzen einiger Test-Programme aufgefallen.

Wenn die ISR zeitkritisch war, dann macht es nichts wenn jetzt die 
Timerinitialisierung länger dauert. Oder war das eh nur ein gefühltes 
Problem?

von Raoul D. (raoul_d219)


Lesenswert?

Carl D. schrieb:
> Raoul D. schrieb:
>> Raoul D. schrieb:
>>> Na prima. Dann werde ich das bei Gelegenheit mal verifizieren, und wenn
>>> es ok ist, mein Optimierungsskript wieder entsorgen ;-)
>>>
>>> (s.a. Beitrag "AVR-GCC generiert unnötigen(?) ISR overhead")
>>
>> Mmh, wohl etwas zu früh gefreut ...
>>
>> Zwar ist mit dem gcc/g++-8 nun dieses "Problem" beseitigt, jedoch sind
>> die enstehenden Codegrößen insgesamt teilweise "wesentlich" größer als
>> beim gcc-7.1.1. Was natürlich mindestens einmal den Spareffekt in den
>> ISRs dieser speziellen Form insgesamt wieder zunichte macht ...
>>
>> Genauer untersucht habe ich das (noch) nicht, mir ist es nur beim
>> Übersetzen einiger Test-Programme aufgefallen.
>
> Wenn die ISR zeitkritisch war, dann macht es nichts wenn jetzt die
> Timerinitialisierung länger dauert. Oder war das eh nur ein gefühltes
> Problem?

Es ging ja von Anfang an nicht um irgendwelche Probleme, sondern es war 
ja nur die Feststellung, dass hier etwas vollkommen Unnützes gemacht 
wird. Und dieser Fall ist m.E. auch noch einfach zu erkennen (s.a. meine 
Skriptlösung).

Aber: meine Programme bestehen ja nicht nur aus einer 
Timerinitialisierung!!!

Allerdings habe bisher nicht untersucht, warum der Optimizer insgesamt 
nun weniger gut arbeitet.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Raoul D. schrieb:
> Es ging ja von Anfang an nicht um irgendwelche Probleme, sondern es war
> ja nur die Feststellung, dass hier etwas vollkommen Unnützes gemacht
> wird. Und dieser Fall ist m.E. auch noch einfach zu erkennen

Im Falle der Tools besteht das "einfach" aus einem Delta von 1200 Zeilen 
und 12 Jahren seit Problem-Report PR20296...

Inzwischen ist auch die Online-Doku aktualisiert:

https://gcc.gnu.org/onlinedocs/gcc/AVR-Function-Attributes.html

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.