Hallo!
Ich habe gemerkt, dass ein Ringpuffer am U(S)ART einiges bringen würde -
ist wohl aber hinreichend bekannt ;)
Also habe ich mir überlegt: "Bau ich das doch in meine uartlib mit
ein!". Gesagt, getan. Aber Essig, dat Ding lüppt nich. Leider sehe ich
selbst nirgends einen Fehler, es müsste theoretisch klappen!
Hier meine Lib (auf das gekürzt, was auch kompiliert wird...:
Dampfente schrieb:> es müsste theoretisch klappen!
Und Praktisch? Was sagt der Debugger?
Dir ist schon klar, dass du das erste Zeichen ohne Interrupt senden
musst? Oder was meinst du, wie oft die ISR(USART_UDRE_vect) aufgerufen
wird?
Klarer Fall: Du startest das Aussenden nicht. Das ist hier das Problem,
denn der TX-Intterupt (UDRE) kommt ja nur wenn man schon ein Zeichen
verschickt hat.
Das heisst man muss das erste Zeichen direkt ins UDR Register schreiben
- aber nur falls nicht schon ein Transfer läuft.
Alternativ kann man auch den TX-Interrupt via Software auslösen. Das
Problem ist jedoch dasselbe: Auch dies darf nur dann stattfinden, wenn
kein TX-Transfer aktiv ist, sonst gibts Datensalat.
Jim Meba schrieb:> Klarer Fall: Du startest das Aussenden nicht. Das ist hier das Problem,> denn der TX-Intterupt (UDRE) kommt ja nur wenn man schon ein Zeichen> verschickt hat.
Klingt logisch, danke!
Angepasst:
[c]int main() {
uart_init(115200UL, UART_DD_BOTH);
sei();
// die kommt NICHT an!
uart_transmit(65);
while ( !( UCSRA & (1<<UDRE)) );
// die kommt an!
UDR = 255;
}
Tja, die 65 (Ascii A) ist nirgends zu entdecken :(
Debugger hab ich gerade nicht hier, kann das EclipsePlugin nicht
anständig (soweit ich weiß)
gez: eine Ente
Unabhängig von der angesprochenen Problematik: Wenn du in deQueue erst
"start" inkrementierst, dann über diesen Index Daten rausholst und erst
dann per Modulo korrigierst, dann kann ein zweifelhafter Zwischenzustand
entstehen, in den ein Interrupt reinrutschen und die Daten durcheinander
bringen kann. Hier wäre eine lokale Variable angebracht, die anfangs
geladen und abschliessend zurück geschrieben wird.
A. K. schrieb:> zweifelhafter Zwischenzustand
Oh, da waren meine Finger wieder schneller als das Hirn - anfangs hatte
es noch Sinn ergeben, das so zu tun, dann wieder was geändert... joa,
passiert. Angepasst und vereinheitlicht:
A. K. schrieb:> Ungeschütze Makros sind Falltüren.
Okay, das habe ich nun auch noch eingebaut, meine Macros sehen jetzt so
aus:
1
#define enQueue(value, buffer, end) { \
2
buffer[end] = value; \
3
end = ((end + 1) % UART_BUFFER_SIZE); \
4
}
5
6
#define deQueue(value, buffer, start) { \
7
start = ((start + 1) % UART_BUFFER_SIZE); \
8
value = buffer[start]; \
9
}
Aber funktionieren tut es immer noch genauso: Nicht.
Peter Dannegger schrieb:> Beitrag "AVR-GCC: UART mit FIFO">> Peter
Bei diesen kommentarlosen Verweisen auf eigene Threads schellen mir zwar
regelmäßig die Eigenlob-Alarmglocken, aber ich unterdrücke das mal ;)
Ich habe deine lib gesehen und ausprobiert - und sie macht ihre Arbeit
nicht besser als meine - und damit ebenso gut wie die lib von Peter
Fleury.
Vielleicht habe ich alles falsch benutzt? Möglich - aber sie ist sowieso
nicht 'intuitiv' benutzbar - schon allein den Baudratenteiler muss man
noch im Hauptprogramm berechnen... :|
Ja, ich habe auf mehreren AVRs (Mega32, Mega16) getestet und damit einen
Hardwaredefekt ausgeschlossen.
gez: eine Ente.
Stelle ich mich hier zu dumm an, um eine Antwort bekommen?
Hat niemand mehr eine Idee?
...oder warum geht's hier scheinbar nicht weiter?
Ich verzweifel hier gerade, Leute :D
gez: eine Ente
Hallo Dampfente (Gast),
auch wenn Peter kurz auf seinen Lib verwiesen hat, muss ich noch
anmerken sie funktioniert hervorragend !
Ich habe sie und auch die "Software UART mit FIFO" hier
Beitrag "Re: Software UART mit FIFO"
zusammengetragen.
Über das Studium seiner Quellen kommst Du zu einer Problemlösung und
Umstellung deiner Programmlogik. Da ist der Fehler.
.
> ...oder warum geht's hier scheinbar nicht weiter?
Ich verstehe mit deiner Beschreibung nicht, was nicht funktioniert - 1)
das Interruptbasierte Senden/Empfangen oder 2) der Ringpuffer. Beim "Es
funktioniert" Fall hattest du ja weder 1) noch 2) benutzt.
1) ist die Voraussetzung und 2) ist die Kür. Daher würde ich zuerst 1)
implementieren und debuggen (was auch das entsprechende Testprogramm
liefert) und dann 2). 2) kann man auch mit Polling prüfen.
Deine Variante 2) mit Makros zu machen, erleichtert weder das Debuggen
von 1) noch von 2). Einen wesentlichen Fallstrick hat A.K. bereits
gezeigt. Es wäre fürs Debuggen wesentlich einfacher, wenn statt Makros
Funktionen verwendet würden. Sollte es nötig sein das aus Platz (?) oder
Performance (?) Gründen als Makros zu machen, kann das später erfolgen.
Uwe S. schrieb:> Hallo Dampfente (Gast),>> auch wenn Peter kurz auf seinen Lib verwiesen hat, muss ich noch> anmerken sie funktioniert hervorragend !
Wie gesagt - vielleicht hab ich auch alles nur falsch benutzt. Ich
bezweifle das gar nicht. Nur Feinheiten im Stil der lib sagen mir
persönlich nicht zu; und dass ein "Plug and Play"-Versuch gescheitert
ist. Mir erschien es da günstiger, meine lib etwas zu erweitern als nach
einer fertigen Lösung zu suchen, die genau zu mir passt. Vielleicht ist
das vorhin falsch rübergekommen.
Uwe S. schrieb:> Über das Studium seiner Quellen kommst Du zu einer Problemlösung und> Umstellung deiner Programmlogik. Da ist der Fehler.
Vielleicht ist dieser Teil beabsichtigt so schwammig. Ich kann
jedenfalls versichern, den Code von P.D. eingesehen und zu 95%
verstanden zu haben (nur AIL und NIL sind mir noch ein Rätsel).
Insgesamt kann ich nur kleinere Unterschiede zu meinem Code finden.
Da wäre die Inter-AVR-Portierbarkeit, die bei mir nur im Hintergrund
steht, bei Peter das automatische an/ausschalten der Sender-ISR nach
Bedarf, und ein paar Speicheroptimierungen mehr, die ich vielleicht
nachträglich einstricke.
Krapao schrieb:> Ich verstehe mit deiner Beschreibung nicht, was nicht funktioniert - 1)> das Interruptbasierte Senden/Empfangen oder 2) der Ringpuffer. Beim "Es> funktioniert" Fall hattest du ja weder 1) noch 2) benutzt.
Ich hab mal einen kurzen Test gemacht und die UDRE_ISR durch eine
Senderoutine ersetzt:
noch ein Zeichen gesendet. Die einzigen Bytes die ankommen, sind die aus
der main (0xFF) und die aus der uart_init (auch 0xFF).
Offensichtlich ist das IRQ-gesteuerte Senden allein schon nicht möglich.
Krapao schrieb:> Einen wesentlichen Fallstrick hat A.K. bereits> gezeigt. Es wäre fürs Debuggen wesentlich einfacher, wenn statt Makros> Funktionen verwendet würden.
Klingt vernünftig, habe ich getan; leider hat das noch keine Besserung
gebracht.
Anselm schrieb:> Was waren deine Beweggründe, die Ringbuffer Funktion in die> UART lib einzubauen?
Übertragungsrate. Ohne den Puffer kann ich bei größeren Übertragungen
nur sehr langsam an den µC senden, was bei Dateiübertragungen Richtung
SD-Karte sehr nervtötend ist. Bsp: Ich will 40 KB abspeichern - ohne
Puffer krieg ich das bisher in etwa 20min auf die Karte. Mit Puffer ist
das (theoretisch) in zwei bis drei Sekunden zu schaffen.
gez: eine Ente
Dampfente schrieb:> ...oder warum geht's hier scheinbar nicht weiter?Lothar Miller schrieb:> Was sagt der Debugger?Dampfente schrieb:> Stelle ich mich hier zu dumm an, um eine Antwort bekommen?
Wenn du nur sagst: ich probier die und probier das, aber keine
Ratschläge annimmst (wie startet man das Senden?) und nicht mal sagst,
was du machst und was nicht geht, was ERWARTEST du dann?
> Offensichtlich ist das IRQ-gesteuerte Senden allein schon nicht möglich.
Doch. Andere können das. Und der Controller gibt das her. Nur: der Start
muss händisch angepackt werden. Aber was sage ich. Das steht im
DATENBLATT (und es wurde wie gesagt hier schon gesagt).
>> Es wäre fürs Debuggen wesentlich einfacher, wenn statt Makros>> Funktionen verwendet würden.> Klingt vernünftig, habe ich getan; leider hat das noch keine Besserung> gebracht.
Und: was ist dabei herausgekommen? Oder ist das geheim?
> Bsp: Ich will 40 KB abspeichern - ohne Puffer krieg ich das bisher> in etwa 20min auf die Karte. Mit Puffer ist das (theoretisch)> in zwei bis drei Sekunden zu schaffen.
Warum glaube ich das nicht?
Was hast du so vermurkst, dass da deiner Meinung nach eine derartige
Steigerung drin ist?
Hallo Lothar,
Sei es mir gegönnt, deinen Beitrag mal zu analysieren - im
ursprünglichsten Wortsinne!
Analysieren kommt vom griechischen: αναλύσειν, und bedeutet "auflösen"
;)
Mögen die Spiele beginnen.
Lothar Miller schrieb:> Wenn du nur sagst: ich probier die und probier das, aber keine> Ratschläge annimmst
Wann habe ich denn mal einen Ratschlag nicht angenommen? Mal sehen...
1
Lothar Miller schrieb im Beitrag #2400718:
2
> Dir ist schon klar, dass du das erste Zeichen ohne Interrupt senden
3
> musst? Oder was meinst du, wie oft die ISR(USART_UDRE_vect) aufgerufen
4
> wird?
5
Habe ich gemacht. Mehr noch - das Programm sendet ZWEI sinnlose Bytes - die eben auch sinnlos bleiben. Siehe dazu die schon vor gefühlten Jahren gepostete Main-Routine. Ratschlag angenommen.
6
A. K. schrieb im Beitrag #2400758:
7
> Wenn du in deQueue erst
8
> "start" inkrementierst, dann über diesen Index Daten rausholst und erst
9
> dann per Modulo korrigierst, dann kann ein zweifelhafter Zwischenzustand
10
> entstehen
11
Ist eingebaut. Die entsprechende Routine sieht nun so aus:
> Es wäre fürs Debuggen wesentlich einfacher, wenn statt Makros
19
> Funktionen verwendet würden. Sollte es nötig sein das aus Platz (?) oder
20
> Performance (?) Gründen als Makros zu machen, kann das später erfolgen.
21
Ratschlag angenommen!
22
A. K. schrieb im Beitrag #2400767:
23
> Ungeschütze Makros sind Falltüren.
24
Huch, ein weiterer Ratschlag, den ich angenommen hatte - das beweist der Zwischenzustand:
25
[c]#define enQueue(value, buffer, end) { \
26
buffer[end] = value; \
27
end = ((end + 1) % UART_BUFFER_SIZE); \
28
}
29
30
#define deQueue(value, buffer, start) { \
31
start = ((start + 1) % UART_BUFFER_SIZE); \
32
value = buffer[start]; \
33
}[/c]
Soll ich weitermachen? Genug? Fein. Bittebitte, komm mir verdammt noch
mal nicht so!
Aber... wieder ruhig Blut. Wenn man schon eine Frage an das allwissende
Internet richtet, muss man ja eigentlich so vorbereitet sein, dass man
die Antwort eigentlich schon kennt. Also weiter.
Lothar Miller schrieb:> Doch. Andere können das. Und der Controller gibt das her. Nur: der Start> muss händisch angepackt werden.
Das ist mir klar. Andere können auch Raketen zum Mond schießen und da
muss der Start auch "händisch angepackt" werden.
Nur wie, zum Teufel, wie?
Ich habe inzwischen den Code von Peter Dannegger, Peter Fleury und vom
RN-Wissen gelesen. Nicht zu vergessen den hier im Wiki. Überall stehen
die gleichen Dinge:
ISR zum Empfangen und zwischenspeichern
ISR zum Senden aus dem Zwischenspeicher
uart_init zum setzen der Baudrate und der Interrupt-Flags, und zum
sonstigen Initialisieren (Frameformat, Datenrichtungen, blabla.)
Und Methoden für put/get aus dem Zwischenspeicher.
Und bei "Anderen" fügt sich das problemlos zu einem interruptgesteuerten
USART zusammen. Nur bei mir nicht, da läuft einfach gar nix, und das
reproduzierbar bei allen AVRs, die hier rumliegen.
Lothar Miller schrieb:> Aber was sage ich. Das steht im DATENBLATT.
Das Datenblatt ist ja wohl die erste Anlaufstelle für sowas, aber danke
für den Verweis. Ich habe die Seiten 140 bis 165 jetzt ein weiteres Mal
gelesen, aber es war nicht so unterhaltsam wie ein gutes Buch. Spaß
beiseite. Dort steht nix, was mir hilft. Trotzdem danke.
Lothar Miller schrieb:> Und: was ist dabei herausgekommen? Oder ist das geheim?
Am Kopf eines jeden Postings ist ein kleiner Bereich für angehängte
Dateien. Manchmal stehen da auch welche - wie hier:
Beitrag "Re: Mal wieder UART mit Ringpuffer."
Wenn du den Debugger meinst - was der ausgespuckt hat? Nix: Die ISRs
werden nie durchlaufen. Wo hab ich das noch gleich erwähnt? Genau,
hier: Beitrag "Re: Mal wieder UART mit Ringpuffer." - ab Absatz 3.
Lothar Miller schrieb:> Warum glaube ich das nicht?> Was hast du so vermurkst, dass da deiner Meinung nach eine derartige> Steigerung drin ist?
Ich glaube, das interessiert hier niemanden. Wie wir schon überaus
wissenschaftlich korrekt festgestellt haben, tu ich ja nix anderes, als
dies und das zu probieren und bin vollkommen beratungsresistent.
Danke, Ente.
PS: Solche Beiträge wie Deiner sind nett, um Neulinge zu verscheuchen,
die nicht in der Lage sind zu recherchieren. Aber überleg vorher bitte
zweimal, ob die Zielperson auch in dieses Register passt.
Ich bin zwar kein Vollprofi, aber eben auch kein Vollpfosten.
Uwe S. schrieb:> Mach dir bitte klar, warum das dort SO steht.
Ich bin Peters Code schon durchgegangen, und seine SBIS-Methode auf
einzelne Bits lesend UND schreibend zuzugreifen finde ich syntaktisch
sehr elegant. Bei Gelegenheit übernehme ich das mal und passe es meinen
Paradigmen an.
Zur Semantik: Hier wird das Bit UDRIE im UCSRB-Register gelöscht bzw.
gesetzt. Der TX-Interrupt wird ja nur gebraucht, wenn etwas im
Sendepuffer ist, also kann er bei leerem Sendepuffer abgeschaltet
werden. Soweit klar.
Meine uart_init schaltet den TX-Interrupt übrigens direkt an - sollte
aber nach meinem Verständnis keinen Unterschied machen - wenn das
aktuelle Primärziel ist: "Übertrage mit Interrupt ein Byte zum Rechner"
Hallo Dampfente,
du hast es leide noch nicht gesehen, der Trick ist beim Senden immer das
ISR-Bit zu setzen, so wird immer wieder ein stehende TX EMPTY ISR neu
gestartet und sie läuft, bis der Puffer leer ist.
Das Erste Zeichen kommt so auch aus dem Puffer und wird nicht per HAND
gesendet.
Nochmal:
Die ISR beendet sich selbst, wenn keine Zeichen mehr im Puffer sind.
Trigger:
Sie wird durch jedes Zeichen, das man in den Puffer schreibt
angestossen.
Klar?
Hier noch der Auszug aus der anderen Lib von Peter Fleury.
Er setzt die selben ISR BITs, also sollte es doch so gehen.
Die Programmlogik ist die Selbe!
1
/*
2
Title: Interrupt UART library with receive/transmit circular buffers
3
Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
Dampfente schrieb:> Meine uart_init schaltet den TX-Interrupt übrigens direkt an
Viele Interrupt-Flags beim AVR setzen sich mit Aufruf der ISR
automatisch zurück. Nicht alle. Der UDRE-Interrupt nicht. Was also
geschieht, wenn in der ISR der Puffer leer ist?
Uwe S. schrieb:> der Trick ist beim Senden immer das> ISR-Bit zu setzen, so wird immer wieder ein stehende TX EMPTY ISR neu> gestartet und sie läuft, bis der Puffer leer ist.
Eigentlich ist das ja sachlich falsch, da in der ISR keine Schleife
benutzt wird um aus dem Puffer zu senden, sondern zeichenweise gesendet
wird, da die ISR aufgerufen wird, sobald der HW-Sendepuffer leer/bereit
ist.
Im Endeffekt läuft sie aber natürlich so wie du es beschreibst ;)
Vielleicht bringts ja was...?
Nein. Keine Änderung. Die manuell gesendeten Daten aus der init-Routine
und dem Mainprogramm kommen an, aber ein uart_transmit(65); bleibt
stumm.
Ich habe sehr wohl verstanden, wie das prinzipiell funktioniert: Der
Interrupt wird solange ausgelöst, wie das UDR-Register bereit ist, Daten
aufzunehmen. Voraussetzung: Interrupts sind per sei(); aktiviert und das
UDRIE-Bit ist auf 1.
Wenn man dann in UDR schreibt, die ISR solange NICHT mehr ausgelöst, bis
das UDR bereit ist, das nächste Byte aufzunehmen.
sei(); rufe ich im main auf, und das UDRIE-Bit ist definitiv gesetzt.
Also muss wohl der HW-Sendepuffer schuld sein, aber auf den warte ich ja
(mehrfach), indem ich Bytes manuell sende. Also muss der auch bereit
sein, ergo MUSS meine ISR eigentlich auslösen - wenn man dem Datenblatt
trauen darf.
Tut sie aber nicht. Warum? Das frage ich euch gerade, ich weiß es auch
nicht.
A. K. schrieb:> Viele Interrupt-Flags beim AVR setzen sich mit Aufruf der ISR> automatisch zurück. Nicht alle. Der UDRE-Interrupt nicht. Was also> geschieht, wenn in der ISR der Puffer leer ist?
Die ISR wird immer wieder aufgerufen, was sehr ineffizient wäre.
Theoretisch. Praktisch passiert bei mir NICHTS.
Uwe S. schrieb:> Er setzt die selben ISR BITs, also sollte es doch so gehen.> Die Programmlogik ist die Selbe!
Jopp, das denke ich auch die ganze Zeit....
gez: eine Ente
end kann man so nicht ändern !
Der Sichtbarkeitsbereicht liegt nur innerhalb der KLAMMERN { }
Stichwort:
end wird der Wert CALL BY VALUE übergeben.
Das trifft natürlich auch auf alle anderen dieser inline .. zu.
Vieleicht magst du ein MACOO anstatt der Funktion ?
Dampfente schrieb:> Die ISR wird immer wieder aufgerufen, was sehr ineffizient wäre.> Theoretisch. Praktisch passiert bei mir NICHTS.
Woran ist dieses "nichts" erkennbar?
Guten Morgen A. K. - die Zeit vergeht...
Nun ich habe nichts falsches geschrieben, nur die Lese und Schreibzeiger
lassen sich so nicht verändern..
Damit läuft der Puffer nicht und alles STEHT. Das hatten wir schon
gelesen.
Uwe S. schrieb:> Nun ich habe nichts falsches geschrieben, nur die Lese und Schreibzeiger> lassen sich so nicht verändern..
Klar, nur hatte er anfangs Makros verwendet, dann wurde ihm oben der Tip
gegeben, Funktionen statt Makros zu verwenden und nun rätst du ihm,
Makros statt Funktionen zu verwenden. ;-)
Aber nicht von mir, dann sollte man sich als Programmierer auch die
Seiteneffekte bewust machen. In diesem Fall gibt es keine.
Mir ist das auch erste durch das DRÜBERSEHEN der Dateien im ZIP File
aufgefallen.
Vielleicht sendet Dampfente noch mal alles und man könnte morgen alle
weiteren Fehler finden.
Bei den Codestückchen schaue ich auch nicht durch, was nun verwendet
wird oder wurde.
.
Uwe S. schrieb:> Vieleicht magst du ein MACOO anstatt der Funktion ?
Danke, genau daher kommt der Fehler auch, es war bis vor Kurzem ein
Makro ;)
Krapao schrieb:> Es wäre fürs Debuggen wesentlich einfacher, wenn statt Makros> Funktionen verwendet würden. Sollte es nötig sein das aus Platz (?) oder> Performance (?) Gründen als Makros zu machen, kann das später erfolgen.
Ich hab jetzt mal einen Pointerzugriff draus gemacht... µC meldet: "A".
Yeah. Natürlich! Er hat den Buffer gefüllt, aber da sich die Indexe
nicht verändert haben, glaubte er hinterher wieder der Buffer wäre leer.
Das war der Fehler.
Danke an Uwe S.!
Die uartlib schreibe ich morgen so fertig, dass sie ordentlich ist und
etwas mehr speicheroptimiert - Dann veröffentliche ich das Ding hier.
Gute Nacht an alle!
gez: eine Ente
Dampfente schrieb:> (nur AIL und NIL sind mir noch ein Rätsel).
Alwas-In-Line bzw. Never-In-Line.
Der AVR-GCC ist etwas störrisch, was das Inlining angeht.
Er möchte kleine Funktionen inlinen, auch wenn das für die Codegröße
kontraproduktiv ist.
Andererseits ist bei größeren Funktionen das einfache "inline" nicht
stark genug, wenn man wirklich inlinen will.
Daher habe ich AIL/NIL definiert, um ihm meinen Willen aufzuzwingen.
Man kann aber auch den Compilerschalter "-fno-inline-small-functions"
benutzten, dann braucht man NIL nicht.
Peter
Peter Dannegger schrieb:> Er möchte kleine Funktionen inlinen, auch wenn das für die Codegröße> kontraproduktiv ist.> Andererseits ist bei größeren Funktionen das einfache "inline" nicht> stark genug, wenn man wirklich inlinen will.
Aha. War mir gar nicht so klar - hab das nur mal irgendwo als Randnotiz
gelesen...
Wie benutzt man diese Defines denn dann? Im Code sind sie nirgends
verwendet, bloß definiert:
1
#define AIL(x) static x __attribute__ ((always_inline)); static x
2
#define NIL(x) x __attribute__ ((noinline)); x
Wenn ich jetzt ein void myFunc(void) { blabla(); } habe, wo kommmt dann
AIL bzw. NIL hin?
gez: eine Ente
Hallo Dampfente,
was Peter mit den beiden Macros zur Verfügung stellt, ist eine
Möglichkeit, schnell eine bestimmte Funktion als Inline-Funktion zu
definieren.
Wann man das eine oder andere Macro anwendet oder liegt deshalb bei dir.
Ich bin dazu übergegangen alle Funktionen, die man auch Inlinen könnte,
als "static" zu deklarieren.
Des weiteren steht in meinen Makefile:
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -fno-inline-small-functions
CFLAGS += -fno-move-loop-invariants
Bei kleinen AVR auch mal
## !!Danach hat man nur noch 256 Byte Stack !!
CFLAGS += -mtiny-stack
Uwe S. schrieb:> Hallo Dampfente,>> was Peter mit den beiden Macros zur Verfügung stellt, ist eine> Möglichkeit, schnell eine bestimmte Funktion als Inline-Funktion zu> definieren.
Jo, das hab ich so weit :)
Meine Frage bezog sich eher darauf, WIE man die Makros anwendet - nicht
WANN :)
gez: eine Ente
Uwe S. schrieb:> Wenn man das Macros expandiert, so folgt:> AIL(void func_ich_bin_inline(uint8_t para1, uint8_t para2 ) )> {> // code> // :> }
Danke, Uwe S.!
gez: eine Ente