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
staticinlinef(...){...};
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:
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
case0:tab[0]();break;
3
case1: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
>case0:tab[0]();break;
3
>case1: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.
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.