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.
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.
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"
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) { ... } |
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__?
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.
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.
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
|
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.