Hi, ich spiele derzeit mit einem USB-fähigen AVR (Atmega32U4) herum und möchte daraus ein Composite Device (cdc-acm und msc) bauen. Die Verwaltung des Gesamtdevices (Endpoint 0, Descriptoren) muss zentral geschehen, alles weitere soll aber jeder Treiber (nach Möglichkeit) für sich behandeln. Alle Endpoints teilen sich einen Interruptvektor, also hatte ich da eine Tabelle im Kopf, wo die Endpoint-spezifischen Handler vermerkt sind und verzweige dann nach Bedarf. Ich arbeite mit C (avr-gcc). Kann ich diese spezifischen Handler in die ISR inlinen, auch über Dateigrenzen hinweg? Was muss ich dem gcc dafür mitteilen? Oder muss ich den Preis eines indirekten Funktionsaufrufs in der ISR bezahlen, wenn ich getrennte Treiber möchte? Eine fertige Bibliothek möchte ich (vorerst) nicht nutzen. Im Augenblick orientiere ich mich an einem kleinen Teensy-Beispiel für cdc und den originalen Datenblättern, Lufa ist mir ein bisschen zu wirr. Gruß, svenska
Du kannst keine ISR mehrfach definieren. Der eigentliche Funktionsaufruf aus der ISR heraus ist ja noch nicht mal das Problem, der kostet selbst mit Parameterübergabe nur ein paar Zyklen. Unschöner ist, daß der gcc zum ISR-Begin alle Register retten, und am Ende wieder herstellen muß, sobald er da einen Funtionsaufruf findet, bei dem er die Sourcecode nicht kennt. Da die ISR aber auch nur eine C-Funktion ist, kannst du da Funktionen so inlinen, wie sich in C Funktionen halt so inlinen lassen. Also entweder alle Funktionen in einem Sourcefile, oder zumindest per include darin eingebunden. Die dann noch static und inline, dann machts der gcc vielleicht sogar. Oliver
Oliver S. schrieb: > Da die ISR aber auch nur eine C-Funktion ist, kannst du da Funktionen so > inlinen, wie sich in C Funktionen halt so inlinen lassen. Die Frage ist, ob das über Dateigrenzen hinweg machbar ist. Wenn nicht, muss ich die Kröte halt schlucken; wirklich schlimm wäre das nicht.
S. R. schrieb: > Die Frage ist, ob das über Dateigrenzen hinweg machbar ist. Ja. Mit Link Time Optimization (LTO) geht das ganz automatisch. Wenn es nur einen Aufrufer einer Funktion gibt, wird diese automatisch ge-inlined. Ganz ohne inline und/oder static keywords.
wenn man eine C-Funktion möglichst immer und ausschließlich auch über Übersetzungseinheiten hinweg ge-inlined haben möchte, schreibt man sie nicht in eine .c-Datei, sondern in die entsprechende Header-Datei und definiert sie
1 | static inline f(...) { ... }; |
Allerdings muß der Compiler sie selbst dann nicht unbedingt inlinen, wenn er nicht will (weil man z.B. nicht optimiert compiliert). Bei gcc kann man in dem Fall noch extra nachhelfen:
1 | __attribute__((always_inline)) |
Dann geht das auch ohne -flto
MaWin schrieb: > Ja. Mit Link Time Optimization (LTO) geht das ganz automatisch. Auch, wenn man das indirekt über einen Funktionspointer in einer (lokal const static deklarierten) Tabelle macht? Also von:
1 | switch(whatever) { |
2 | case 0: tab[0](); break; |
3 | case 1: tab[1](); break; |
4 | default: break; |
5 | }
|
zu:
1 | if(whatever == 0) { |
2 | /* die funktion, auf die tab[0] zeigt */
|
3 | } elsif(whatever == 1) { |
4 | /* die funktion, auf die tab[1] zeigt */
|
5 | }
|
automatisch? Denn das kann ich mir nicht vorstellen.
S. R. schrieb: > MaWin schrieb: >> Ja. Mit Link Time Optimization (LTO) geht das ganz automatisch. . > Auch, wenn man das indirekt über einen Funktionspointer in einer (lokal > const static deklarierten) Tabelle macht? > > Also von: >
1 | > switch(whatever) { |
2 | > case 0: tab[0](); break; |
3 | > case 1: tab[1](); break; |
4 | > default: break; |
5 | > } |
6 | >
|
. > zu: >
1 | > if(whatever == 0) { |
2 | > /* die funktion, auf die tab[0] zeigt */ |
3 | > } elsif(whatever == 1) { |
4 | > /* die funktion, auf die tab[1] zeigt */ |
5 | > } |
6 | >
|
> > automatisch? Denn das kann ich mir nicht vorstellen. Bei LTO wird die komplette interne Darstellung einer "C-Datei" oder korrekt Übersetzungseinheit an den Linker übergeben, d.h. die Optimierung kann dort mit der gesammelten Info über alle Code-Schnipsel stattfinden.
Hinterher mal im Assembler-Listing nachschauen, was der Compiler jetzt tatsächlich draus gemacht hat, schadet aber trotzdem nicht. Oliver
S. R. schrieb: > automatisch? Denn das kann ich mir nicht vorstellen. Ich weiß nicht, ob der gcc das tut. Aber ich halte es nicht für unmöglich. Es müss(t)en halt mehrere Optimierungen zusammenarbeiten. Ich denke aber, dass eher das switch rausfliegen wird und Arithmetik auf die Tabelle angewendet wird. Am Ende ist das aber auch ein Spezialfall. Nimm halt keine Tabelle.
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.