Forum: Compiler & IDEs ISR Vektor nur wenn init-Funktion aufgerufen wird


von N. G. (newgeneration) Benutzerseite


Lesenswert?

Hallo Forum,

wie immer eine spezielle Frage von mir:

Ich habe hier einen AVR der verschiedene Hardwareteile hat, bei dem 
jeder eine oder mehrere Interrupts besitzt.
Dadurch dass die dazugehörigen Vektoren nicht durch das Programm, 
sondern durch die Hardware aufgerufen wird, muss im Linkerfile ein 
KEEP(vectors) (oder so ähnlich) stehen. Dadurch erzeugt jeder Vektor der 
im Programm definiert ist einen Eintrag im Output-File. Das ist ja 
generell auch richtig und wichtig.

Aber nun kann es sein, dass z.B. ein AVR mehrere UARTs hat und nur einer 
davon benutzt wird. Somit wären die restlichen ISRs zwar enthalten, 
bleiben aber immer ungenutzt.

Bei mir hat jeder Hardware-Teile seine eigene init-Funktion. Könnte man 
dem Linker irgendwie beibringen, dass er die Vektoren nur behalten soll, 
wenn die dazugehörige init-Funktion aufgerufen wird?

Ein einfaches Nein genügt ;)

mit freundlichen Grüßen
N.G.

von Karl M. (Gast)


Lesenswert?

Warum sollte man das machen ?

Der ISR-Vector-Block muss doch fast immer da sein.

Außer man verwendet keine Interrupt-Routinen, dann kann man sich bis auf 
den Reset-Vektor alle Sparen.

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Es geht mehr oder weniger ums Speicher sparen

Also kann man den Linker irgendwie sagen:
"Behalte diesen Vektor nur, wenn die Funktion x aufgerufen wurde"

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

N. G. schrieb:
> Bei mir hat jeder Hardware-Teile seine eigene init-Funktion. Könnte man
> dem Linker irgendwie beibringen, dass er die Vektoren nur behalten soll,
> wenn die dazugehörige init-Funktion aufgerufen wird?

Ja, die entsprechenden Module (i.d.R. nur eines) werden einfach nicht 
hinzugelingt.

Dazu wird die init nicht explizit, z.B. von main, aufgerufen, sondern 
die Initialisierung geschieht durch einen Konstruktor per Modul:
1
__attribute__((__constructor__,__used__,__unused__))
2
static void module_init (void) { ... }

von N. G. (newgeneration) Benutzerseite


Angehängte Dateien:

Lesenswert?

anbei mal ein Beispiel was ich meine:

(Gebaut für einen ATmega2560 - ja ein schlechtes Beispiel, weil Platz 
hat der genug, aber um das "Problem" zu verdeutlichen ist es perfekt)

Abgesehen vom Startup-Code, der Vektortabelle, der (leeren) 
main-Funktion und dem exit-Code ist nichts da, ist ja auch klar, der 
Controller soll ja nichts machen.
Aber: ein bischen mehr ist halt doch da: 9 nicht ganz kleine Vektoren

macht schon mal über 1200 byte Code, bei dem ich den größten Teil gar 
nicht will...

Johann L. schrieb:
> N. G. schrieb:
>> Bei mir hat jeder Hardware-Teile seine eigene init-Funktion. Könnte man
>> dem Linker irgendwie beibringen, dass er die Vektoren nur behalten soll,
>> wenn die dazugehörige init-Funktion aufgerufen wird?
>
> Ja, die entsprechenden Module (i.d.R. nur eines) werden einfach nicht
> hinzugelingt.
>
> Dazu wird die init nicht explizit, z.B. von main, aufgerufen, sondern
> die Initialisierung geschieht durch einen Konstruktor per
> Modul:__attribute__((_constructor_,__used__,__unused__))
> static void module_init (void) { ... }

Okay, das sieht schon mal interessant aus. Aber darf ein Kontruktor 
static sein? Und warum _used_,__unused__?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

N. G. schrieb:
> Johann L. schrieb:
>> N. G. schrieb:
>>> Bei mir hat jeder Hardware-Teile seine eigene init-Funktion. Könnte man
>>> dem Linker irgendwie beibringen, dass er die Vektoren nur behalten soll,
>>> wenn die dazugehörige init-Funktion aufgerufen wird?
>>
>> Ja, die entsprechenden Module (i.d.R. nur eines) werden einfach nicht
>> hinzugelingt.
>>
>> Dazu wird die init nicht explizit, z.B. von main, aufgerufen, sondern
>> die Initialisierung geschieht durch einen Konstruktor per
>> Modul:__attribute__((_constructor_,__used__,__unused__))
>> static void module_init (void) { ... }
>
> Okay, das sieht schon mal interessant aus. Aber darf ein Kontruktor
> static sein?

Ja. I'm not joking :-)

> Und warum _used_,__unused__?

used: Selbst wenn kein Aufruf existiert, wird die (static) Funktion 
nicht vom Compiler entsprgt.  Kann aber gut sein, dass das für 
Konstruktoren eh der Fall ist, weil die i.d.R. ja nicht aufgerufen 
werden. Aber used schadet nicht.

unused: Es gibt keine Warnung, obwohl eine static nicht-inline Funktion 
nie verwendet wird.  Ditto was gcc-Wissen bzgl. Konstruktor angeht.

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Johann L. schrieb:
> Ja. I'm not joking :-)

Hätte ich von dir auch nicht erwartet ;)

>> Und warum used,__unused__?
>
> used: Selbst wenn kein Aufruf existiert, wird die (static) Funktion
> nicht vom Compiler entsprgt.  Kann aber gut sein, dass das für
> Konstruktoren eh der Fall ist, weil die i.d.R. ja nicht aufgerufen
> werden. Aber used schadet nicht.
>
> unused: Es gibt keine Warnung, obwohl eine static nicht-inline Funktion
> nie verwendet wird.  Ditto was gcc-Wissen bzgl. Konstruktor angeht.

Okay, mit der Erklärung logisch, auf den ersten Blick aber paradox.

von Peter D. (peda)


Lesenswert?

N. G. schrieb:
> Aber nun kann es sein, dass z.B. ein AVR mehrere UARTs hat und nur einer
> davon benutzt wird. Somit wären die restlichen ISRs zwar enthalten,
> bleiben aber immer ungenutzt.

Wo ist das Problem?
Du weißt doch schon zur Compilezeit, ob und welche UART Du benutzt:
1
#ifdef UART0_RX_BUFF_SIZE
2
// code
3
#endif
4
#ifdef UART1_RX_BUFF_SIZE
5
// code
6
#endif
7
#ifdef UART2_RX_BUFF_SIZE
8
// code
9
#endif
10
#ifdef UART3_RX_BUFF_SIZE
11
// code
12
#endif

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Hallo Peter,

ja theoretisch schon.
Im Prinzip mache ich das meist auch so, nur dachte ich, dass es vllt. 
eine Trickreichere, elegantere Lösung gibt.

Das man sich damit auch Probleme (z.B. beim Compilerwechsel) einholen 
kann, dürfte klar sein.

von Peter D. (peda)


Lesenswert?

N. G. schrieb:
> Im Prinzip mache ich das meist auch so, nur dachte ich, dass es vllt.
> eine Trickreichere, elegantere Lösung gibt.

Ich sag mal, ein Funktionsaufruf kann keinen Code erzeugen. Und wenn man 
eine Funktion nicht aufruft, ist ja auch ihr Code überflüssig.
Man könnte natürlich ein Macro schreiben, was Code enthält und nach 
außen hin wie ein Funktionsaufruf aussieht.

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.