Hallo zusammen, ich habe hier auf einem ATMega2560 eine ISR, die serielle Daten entgegen nimmt und in einem Puffer ablegt. Nach dem Empfang des letzten Zeichen läuft eine Auswertung direkt in der ISR, die Daten in einem Array ablegt. Passt auch alles und funktioniert reibungslos. In der ISR werden 8 Register gesichert und wieder hergestellt. Jetzt ist bei der Auswertung noch etwas hinzugekommen, was dazu führt, dass der Compiler der Meinung ist, 27 Register sichern (und wieder herstellen) zu müssen. Gut, wenn er meint... Zeitlich passt das auch noch in den Rahmen, mich ärgert aber, dass bei einer durchschnittlichen Telegrammlänge von 10 Zeichen 342 Befehle für vollkommen sinnlose push/pop-Orgien verbraten werden, da der diese Ressourcen benötigende Programmteil garnicht durchlaufen wird. Im Assembler hätte ich die Rettung zusätzlich benötigter Register direkt in den entsprechenden Programmabschnitt gepackt. Frage: Kann ich das auch dem Compiler beibiegen und wenn ja, wie? Thomas
Grundsätzlich kann man darauf hoffen, dass der Compiler dies beim Optimieren auch sieht. Aber: Kannst du nach Empfang des letzten Zeichens nicht einfach ein Flag setzen und die Auswertung dann in der Hauptschleife machen? Das ist IMHO die sauberere Lösung, wenn man die Zeit dazu hat.
@ Thomas P. (topla) >ich habe hier auf einem ATMega2560 eine ISR, die serielle Daten entgegen >nimmt und in einem Puffer ablegt. Das ist normal. > Nach dem Empfang des letzten Zeichen >läuft eine Auswertung direkt in der ISR, die Daten in einem Array >ablegt. Das schon weniger. Muss das sein? Kann man nicht auch ein Signal an die Hauptschelife senden? Siehe Interrupt. > Passt auch alles und funktioniert reibungslos. In der ISR werden >8 Register gesichert und wieder hergestellt. Jetzt ist bei der >Auswertung noch etwas hinzugekommen, was dazu führt, dass der Compiler >der Meinung ist, 27 Register sichern (und wieder herstellen) zu müssen. >Gut, wenn er meint... Du hast wahrscheinlich eine Funktion aufgerufen. >Kann ich das auch dem Compiler beibiegen und wenn ja, wie? Poste deine ISR als Anhang. Dann reden wir weiter. Wahrscheinlich muss man die Funktionen als Inline deklarieren. Oder einfach direkt als Code in die ISR packen.
Falk B. schrieb: > Das schon weniger. Muss das sein? Kann man nicht auch ein Signal an die > Hauptschelife senden? Siehe Interrupt. Ist mir bekannt, wird dann u. U. aber zeitkritisch zwischen den nächsten eintreffenden Daten und der Umlaufzeit in der Hauptschleife. Da sich diese Verfahrensweise schon auf dem DS80C320 bewährt hat, wollte ich da jetzt nicht alles grundsätzlich neu erfinden. > Du hast wahrscheinlich eine Funktion aufgerufen. Nein, ist eigentlich nur Bitschubserei und Ablage in einem Array. > Poste deine ISR als Anhang. Dann reden wir weiter. Da ist sie. Thomas
@ Thomas P. Könntest Du bitte den Compiler nennen (und dessen genaue Version) sowie die Compilerflags, die beim compilieren der ISR gesetzt sind, posten?
@Thomas P. (topla) >> Du hast wahrscheinlich eine Funktion aufgerufen. >Nein, ist eigentlich nur Bitschubserei und Ablage in einem Array. Hmm, was hängt aber hinter den Macros? XBUS_SEND_EIN; Der Rest sieht normal aus. Hmmm?
Falk B. schrieb: > Hmm, was hängt aber hinter den Macros? > > XBUS_SEND_EIN; #define XBUS_SEND_EIN PORTG |= (1<<XBUS_DIR) > Der Rest sieht normal aus. Hmmm? @Klaus (Gast): avr-gcc (avr_8_bit_gnu_toolchain_3.4.1_798) 4.6.2 unter AVRStudio 4.19 -Wall -gdwarf-2 -std=gnu99 -gstrict-dwarf -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums Thomas @ Sabe (Gast): freut mich, wenn es Dir gut geht.
So weit ich weiss verschiebt zumindest GCC das sichern der Register nicht nach hinten, sondern macht es immer in einem Rutch am Anfang. Der nur selten benutzte Code nutzt ggf. schon relativ viele Register wegen der Arrayzugriffe und >> operatoren. Auf 27 Register zu kommen ist da aber schon viel. Eine Optimierung wäre ggf. bei den Abfragen über die shift operatoren möglich. Es hängt noch von den Datentyen ab. Ggf. ließe sich der Konstante Vergleichswert verschieben um die Bits abzufragen, statt die Werte aus der Tabelle zu schieben.
Ja, sieht so aus. Sowas: switch (xbus_ebuf[i+2] & 0b01100000) ist im Registerbedarf teuer. Macht ja auch nichts, so richtig stören mich eigentlich nur die vielen unnötigen push/pop. Irgendwie hätte ich bei den ganzen Arrayzugriffen auch die eine oder andere Multiplikation erwartet, aber der addiert sich nur zu Tode. Thomas
Man kann den SPM READY Interrupt freigeben und dann in dessen Handler die Auswertung machen.
Thomas P. schrieb: > Irgendwie hätte ich bei den ganzen Arrayzugriffen auch die eine oder > andere Multiplikation erwartet, aber der addiert sich nur zu Tode. keine cpu addiert sich zu tode, denn das ist das, was sie am besten kann. Hast du mal nachgerechnet, ob eine multiplikation (in deinem Falle) überhaupt schneller wäre?
Kaj schrieb: > Hast du mal nachgerechnet, ob eine multiplikation (in deinem Falle) > überhaupt schneller wäre? Nein, nachdem ich hier mehrfach darauf hingewiesen wurde, mich statt um die Arbeit des Compilers lieber um mein Programm zu kümmern. Im Zusammenhang mit der push/pop-Orgie fiel mir nur auf, das der 8051-Code in diesem Umfeld mehrere MUL aufweist. Peter D. schrieb: > Man kann den SPM READY Interrupt freigeben und dann in dessen Handler > die Auswertung machen. Hallo Peter, tut mir leid, ich bekomme keinen Zusammenhang zwischen Datenempfang auf einer seriellen Schnittstelle und Interrupt beim Schreiben in den Programmspeicher hin. Thomas
Thomas P. schrieb: > Hallo Peter, > > tut mir leid, ich bekomme keinen Zusammenhang zwischen Datenempfang auf > einer seriellen Schnittstelle und Interrupt beim Schreiben in den > Programmspeicher hin. Wenn ich das richtig verstehe, meint Peter, die Auswertung in den SPM-Interrupt auszulagern. Diesen gibst du dann frei, wenn dein String komplett empfangen ist. Dadurch wird dieser sofort ausgeführt, weil der Programmspeicher bereit zum Schreiben ist (vermute ich nur, habs nicht nachgelesen!). --> Deine Auswertung erfolgt auch 'sofort' und nicht erst in der main loop, aber du hast nicht bei jeder UART RX ISR die ganzen push/pop drin sondern nur im (selten ausgeführten) SPM Ready Interrupt. Mit Schreiben auf den Programmspeicher hat das nix zu tun, aber der Interrupt kann gut für andere Zwecke missbraucht werden.
Thomas P. schrieb: > Jetzt ist bei der > Auswertung noch etwas hinzugekommen, was dazu führt, dass der Compiler > der Meinung ist, 27 Register sichern (und wieder herstellen) zu müssen. > Gut, wenn er meint... Meistens meint er das zu meinen müssen, wenn aus der ISR eine andere Funktion aufgerufen wird, die er nicht sieht. Dann kann er nur alle Register sichern. Wenn du also eine selbstgeschriebene Funktion aus der ISR heraus aufrufst, pack die mal zu der ISR in die .c-Datei. Dann wird es besser. Oliver
@ chris (Gast): Danke für den Hinweis, hätte mir ja denken können, dass von Peter solche genialen Gedanken kommen. Wäre echt eine Möglichkeit. @ Oliver S.: Den Gedanken hatte Falk ja oben auch schon, ist aber bis auf ein Makro nicht so (siehe Dateianhang). Sieht schon spannend aus: ISR(USART0_RX_vect) { 167a: 1f 92 push r1 167c: 0f 92 push r0 167e: 0f b6 in r0, 0x3f ; 63 1680: 0f 92 push r0 1682: 0b b6 in r0, 0x3b ; 59 1684: 0f 92 push r0 1686: 11 24 eor r1, r1 1688: 5f 92 push r5 168a: 6f 92 push r6 168c: 7f 92 push r7 168e: 8f 92 push r8 1690: 9f 92 push r9 1692: af 92 push r10 1694: bf 92 push r11 1696: cf 92 push r12 1698: df 92 push r13 169a: ef 92 push r14 169c: ff 92 push r15 169e: 0f 93 push r16 16a0: 1f 93 push r17 16a2: 2f 93 push r18 16a4: 3f 93 push r19 16a6: 4f 93 push r20 16a8: 5f 93 push r21 16aa: 6f 93 push r22 16ac: 7f 93 push r23 16ae: 8f 93 push r24 16b0: 9f 93 push r25 16b2: af 93 push r26 16b4: bf 93 push r27 16b6: cf 93 push r28 16b8: df 93 push r29 16ba: ef 93 push r30 16bc: ff 93 push r31 Thomas
Thomas P. schrieb: > Sieht schon spannend aus: > ISR(USART0_RX_vect) > { > 167a: 1f 92 push r1 > [...] > 16bc: ff 93 push r31 Und? Benutzt er die auch alle in der ISR? Wenn ja, wo? Zeig doch bitte mal die komplette ISR in der ASM-Version.
:
Bearbeitet durch Moderator
Wenn man wenigstens eine Idee hätte, welche der vielen undeclared identifieres nun Variablen, Konstanten etc. sind (sodass man compilierbaren Code bekommt), dann wäre es wohl leichter, dir da Ratschläge zu geben. Ich hab's erstmal aufgegeben, das Ding zum Compilieren zu bekommen.
Jörg W. schrieb: > Ich hab's erstmal aufgegeben, das Ding zum Compilieren zu bekommen. Hallo Jörg, danke für Deine Bemühungen. Wenn es zum Erkenntnisgewinn beiträgt, setze ich mich hin und suche die verschiedenen Definitionen zusammen. Allerdings habe ich für mich jetzt erstmal mitgenommen, dass es ohnehin nicht ohne Tricks möglich ist, die Registerrettung an die Stelle im Programmablauf zu schieben, die diese auch benötigt. @ Frank M. (ukw): Nein, es werden wohl nicht alle Register auch wirklich benutzt, keine Ahnung was den Compiler zu der Annahme treibt. Thomas
Thomas P. schrieb: > Allerdings habe ich für mich jetzt erstmal mitgenommen, dass es ohnehin > nicht ohne Tricks möglich ist, die Registerrettung an die Stelle im > Programmablauf zu schieben, die diese auch benötigt. Da bin ich mir eben noch nicht ganz so sicher.
Ich habe das mal alles zusammengefegt; sieht nicht schön aus, sollte aber compilierbar sein - hoffe ich. thomas
Thomas P. schrieb: > sollte aber compilierbar sein Ist es offenbar nicht. Bereits die erste Zeile führt zu einem Fehler.
Johann L. schrieb: > Ist es offenbar nicht. 'main()' fehlt auch. Ich könnte mir vorstellen, dass der Compiler versucht, die Bitfelder durch exzessive Registernutzung einigermaßen optimal einzubinden.
Ralf G. schrieb: > 'main()' fehlt auch. Es geht ja nur um ein Modul, und um ein solchen zu compilieren braucht's keine main: Es recht azs, wenn ein modul.c zu einem modul.o übersetzbar ist, d.h.:
1 | avr-gcc -c modul.c ... |
ohne Fehler zu produzieren ausgeführt werden kann. Der einfachste Weg, um an für andere reproduzierbaren Code zu gelangen, ist den Optionen -v -save-temps zuzufügen, und das i-File samt Optionen zu posten. Wirklich toll ist diese Methode aber nicht, da im i-File alle Makros und Includes aufgelöst sind, so dass das .i schwer zu lesen ist. Für einen richtigen COMPILIERBAREN Testfall, der nicht gleich alle potentiellen Helfer in die Flucht schlägt wegen o nicht ohne Fehler übersetzbar (fehlende Deklarationen, Macros, etc.) o Optionen oder Tool-Version werden verheimlicht o Code-Formatierung wie Kraut & Rüben o Code-Verschleierung per "...", // hier stand ein Code etc. o beliebig verhachstückte Code-Schnippel, die per Copy & Paste aus der Quelle herausgebrochen wurden o Absolutes Unverständnis, was ANDERE benötigen, um das Problem nachzuvollziehen
Thomas P. schrieb: > tut mir leid, ich bekomme keinen Zusammenhang zwischen Datenempfang auf > einer seriellen Schnittstelle und Interrupt beim Schreiben in den > Programmspeicher hin. Der UART-Interrupt schreibt in eine FIFO und macht die Paket-Ende-Erkennung. Bei Paket-Ende enabled er den SPM-Interrupt. Dieser wiederum disabled sich, erlaubt andere Interrupts und wertet dann in aller Ruhe das Paket aus. Der SPM-Interrupt wird damit als SW-Interrupt verwendet. Auch Interrupts, deren Pending Bit nach Reset gesetzt ist, können als SW-Interrupt verwendet werden, z.B. ein nicht benutztes USARTx-UDRE.
Thomas P. schrieb: > sieht nicht schön aus, sollte > aber compilierbar sein - hoffe ich. Warum so ängstlich? Ein simpler Klick auf "Build" hätte sofort aus der Hoffnung Gewißheit machen können.
Johann L. schrieb: > Bereits die erste Zeile führt zu einem Fehler. Kannst du aber auskommentieren, dann compiliert es. So flexibel bin ich dann noch. ;-) GCC 4.7.2 rettet R15 … R31 (und natürlich R0/R1). GCC 4.9.3 rettet R14 … R31 und R0/R1, generiert aber insgesamt 10 Byte kleineren Code. Scheint beides schon mal besser zu sein als bei Thomas. Einen 5er GCC habe ich jetzt nicht noch gebaut. Sinnvoller wäre es schätzungsweise zu sehen, ob man mit irgendwelchen -f-Optionen noch bisschen Finetuning erreicht, aber Johann, da kennst du dich sicher besser aus.
Hallo Johann, ja, ich weiß, dass ich hier der Depp bin, und zu dem habe ich mich auch noch selber gemacht, indem ich in einem Anfall von Wahnsinn beschlossen habe, das Projekt statt in Assembler in C zu realisieren. Ich habe extra den ganzen Definitionsteil in die angehangene Datei eingefügt, damit nicht so viele includes mitgeliefert werden müssen. Dabei habe ich das Entfernen der ersten Zeile verbrummt, blöd, weil der Fehler hier wegen der vorhandenen Datei (auch wenn nix mehr drin steht) eben nicht auftaucht. Tool-Version und Optionen stehen etwas weiter oben. Die Formatierung passt im AVR-Studio einwandfrei, da bleibt wohl was unterwegs auf der Strecke. Verschleiert ist hier garnichts, der Code kommt 1:1 aus dem Projekt. Es sind auch keine kopierten Codeschnipsel, sondern die ISR ist komplett im derzeitigen Zustand, wenn auch noch nicht vollständig. Hat aber mit meiner ursprünglichen Anfrage ("Warum sichert der Compiler alle Register am ISR-Anfang und nicht erst dann, wenn er die Register wirklich braucht und kann man das beeinflussen?") überhaupt nichts zu tun. @Peter Dannegger Ich bin da nicht ängstlich, aber die Antwort von Johann hat doch gleich gezeigt, dass das, was bei mir einwandfrei funktioniert, bei anderen nicht auch so sein muss - deshalb der Hinweis. Danke für Erklärung mit dem SPM-Int, mit Hilfe von chris war ich dann gestern schon selber auf die richtige Spur gekommen. Thomas
Jörg W. schrieb: > GCC 4.7.2 rettet R15 … R31 (und natürlich R0/R1). > GCC 4.9.3 rettet R14 … R31 und R0/R1, generiert aber insgesamt 10 ... und die Register werden auch alle verwendet. (Wenn mir nicht eins durch die Lappen gegengen ist.)
Thomas P. schrieb: > Die Formatierung passt im AVR-Studio einwandfrei, da bleibt wohl was > unterwegs auf der Strecke. Das ist das übliche Dilemma: die Unix-Welt rückt bei einem TAB-Zeichen gern auf eine durch 8 teilbare Position vor (das entspricht dem, wie es eben seit DECs VT100 in der Hardware voreingestellt ist), die Windows-Welt in aller Regel auf eine durch 4 teilbare. Da das bisschen Speicherplatz heutzutage nichts mehr kostet, kommt man im Sinne der Les- und Austauschbarkeit besser, die Einrückungen nur durch Leerzeichen vornehmen zu lassen.
Jörg W. schrieb: > Da das bisschen Speicherplatz heutzutage nichts mehr kostet, kommt > man im Sinne der Les- und Austauschbarkeit besser, die Einrückungen > nur durch Leerzeichen vornehmen zu lassen. Ja, ich habe den Haken in den options vom Editor gefunden und gesetzt. Man muss aber erstmal drauf kommen, dass man ein Problem hat. Thomas
...ohne den Code übersetzt zu haben: Folgendes scheint nicht ganz
unproblematisch.
#1
> int verr:1;
1-Bit signed Variablen können nur die Werte -1 oder 0 annehmen. Im Code
wird aber z.B. gegen 1 getestet. Solche Vergleiche sind immer false!
#2
Code wie
1 | if ((wdat[((xbus_ebuf[i+1])<<2) | (xbus_ebuf[i+2]>>6)].lage) != ((xbus_ebuf[i+2]) & 3)) |
ist zum einen schlecht lesbar und taucht zig-mal auf, insbesondere der Ausdruck für den Array-Index in wdat[]. Weil Daten geschreiben werden, darf der so berechnete Index nicht wiederverwendet werden, sondern muss wegen den Strict-Aliasing Regeln von C immer wieder neu gelesen und berechnet werden. #3 Wenn du schon Bitfelder verwendest, dann leg die "ganzen" Komponenten wie 8-Bit breite Felder an den Anfang oder lass sie wenigstens an geraden (durch 8 teilbaren) Bit-Offsets starten. #4 Beim besten Willen... der Quellcode ist eine Zumutung, ich hab's aufgegeben das zu lesen. Dementsprechend ist auch eine Bewertung des vom GCC erzeugten Codes nicht möglich. o Vermeide TABs. Jeder halbwegs ordentliche Editor erlaubt es, (automatisch) SPACEs anstatt TABs zu verwenden, und zwar OHNE dass man beim Editieren was davon merkt. Das TABs nicht protabel sind und die Lesbarkeit massic einschränken, wirst du kaum von der Hand weisen können. o Versuche, immer wieder auftretende Sequenzen als (inline) Funktionen auszulagern. o Code wie
1 | rmdat[(xbus_ebuf[i+1])>>2] |= (xbus_ebuf[i+2] & 0x0f); |
ist inhärent schlecht wartbar: Währewnd der Verarbeitung werden ständig die Indices der zu verarbeitenden Daten (xbus_ebuf[]) gepatcht. Das Index-Array scheint ein wilder Zoo unterschiedlichster Daten zu sein.
So, auf Grund Deiner Hinweise habe ich angefangen, den Code zu überarbeiten > #1 gegen uint8_t ausgetauscht, längerfristig wird das noch umgestellt > #2 neue Variablen eingeführt, die die erneuten Zugriffe auf den Empfangspuffer unnötig machen sollten > #3 liegen sie doch? > #4 Editor angepasst, im Quellcode Tabs ersetzt > o Versuche, immer wieder auftretende Sequenzen als (inline) Funktionen > auszulagern. Schon wieder eine neue Baustelle, muss ich mir mal anlesen. > o Code wie
1 | rmdat[(xbus_ebuf[i+1])>>2] |= (xbus_ebuf[i+2] & |
2 | > 0x0f); |
ist inhärent schlecht wartbar: Währewnd der Verarbeitung > werden ständig die Indices der zu verarbeitenden Daten (xbus_ebuf[]) > gepatcht. Das Index-Array scheint ein wilder Zoo unterschiedlichster > Daten zu sein. Siehe #2, für die Aufteilung der angelieferten Daten kann ich aber wirklich nichts. Thomas
Wird die Auswertung nach dem letzten Zeichen der seriellen Übertragung über den SPM-Interrupt ausgelagert, will der Compiler noch 9 Register sichern. Ist schon deutlich besser, es bleibt aber die etwas enttäuschende Erkenntnis, dass der Compiler nicht in der Lage ist, benötigte Ressourcen erst im Bedarfsfall zu frei zu räumen, speziell bei ISR, wo Laufzeit doch eine Rolle spielt. Thomas
Thomas P. schrieb: > Ist schon deutlich besser, es bleibt aber die etwas > enttäuschende Erkenntnis, dass der Compiler nicht in der Lage ist, > benötigte Ressourcen erst im Bedarfsfall zu frei zu räumen, speziell bei > ISR, wo Laufzeit doch eine Rolle spielt. Die gesicherten Register werden alle in der ISR auch verwendet! Nichts mit prophylaktisch.
Thomas P. schrieb: > es bleibt aber die etwas enttäuschende Erkenntnis, dass der Compiler > nicht in der Lage ist, benötigte Ressourcen erst im Bedarfsfall zu frei > zu räumen Hajo, so isch des. Die Sicherung der benötigten Ressourcen auf dem Stack erfolgt immer bereits beim Eintritt in eine Funktion (Johann kann mich gern widerlegen). Alternative wäre in deinem Falle natürlich wirklich, die ISR mal in Assembler zu zimmern. Dann kannst du initial nur das Notwendigste sichern und für den Rest dann eine C-Funktion aufrufen, bei der du zuvor das „Komplettprogramm“ abarbeitest (also alle gemäß ABI zu sichernden Register retten).
Jörg W. schrieb: > Die Sicherung der benötigten Ressourcen auf dem > Stack erfolgt immer bereits beim Eintritt in eine Funktion Sogar der Compiler will die Übersicht behalten ;-)
Ralf G. schrieb: > Die gesicherten Register werden alle in der ISR auch verwendet! Nichts > mit prophylaktisch. Jein, im kritischen Pfad, also beim Durchlaufen des Auswertungsteils schon, aber der wird eben im Durchschnitt nur bei jedem 10. Aufruf angesprochen. Nett wäre es eben, wenn die für diesen Pfad benötigten Register erst dann gesichert würden, wenn dieser auch wirklich durchlaufen wird, also nach der Verzweigung eben. Thomas
Thomas P. schrieb: > Sieht schon spannend aus: > ISR(USART0_RX_vect) > { > 167a: 1f 92 push r1 > 167c: 0f 92 push r0 > 167e: 0f b6 in r0, 0x3f ; 63 > 1680: 0f 92 push r0 > 1682: 0b b6 in r0, 0x3b ; 59 > 1684: 0f 92 push r0 > 1686: 11 24 eor r1, r1 /* wird bei mir nicht gesichert (gcc 4.7.2): > 1688: 5f 92 push r5 > 168a: 6f 92 push r6 > 168c: 7f 92 push r7 > 168e: 8f 92 push r8 > 1690: 9f 92 push r9 > 1692: af 92 push r10 > 1694: bf 92 push r11 > 1696: cf 92 push r12 > 1698: df 92 push r13 */ Thomas P. schrieb: > Jein, im kritischen Pfad, also beim Durchlaufen des Auswertungsteils > schon, aber der wird eben im Durchschnitt nur bei jedem 10. Aufruf > angesprochen. Nett wäre es eben, wenn die für diesen Pfad benötigten > Register erst dann gesichert würden, wenn dieser auch wirklich > durchlaufen wird, also nach der Verzweigung eben. Aah, verstehe. Jörg W. schrieb: > Alternative wäre in deinem Falle natürlich wirklich, die ISR mal in > Assembler zu zimmern. Ich bin hier nicht der Experte, aber da hätte man sich die der Sicherheit dienenden Zugriffe auf die Bitfelder ja sparen können. Nur zum 'Umlagern' von 'push/ pop' würde ich mir das nicht antuen. Die Register wird man trotzdem für die Indizes und das Vorhalten der Zwischenergebnisse in den Abfragen brauchen. Bitfelder rausschmeißen ergibt zwar weniger Code, aber die Registersicherung wird nicht kürzer. Der LTO hilft dem Compiler bei der Codgröße enorm, spart jedoch nur noch r14 ein.
Bei allem Engagement sollte man doch aber bitte das Wesentlich nicht aus den Augen verlieren. https://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Prinzipien_der_Optimierung
Man sollte aber nicht zu tode optimieren. Der kleinst mögliche UART-Teiler ist 8, d.h. der Interrupt hat mindestens 80 Zyklen zur Verfügung. Da die UART bis zu 3 Byte puffern kann, kann man auch eine Loop schreiben, die am Ende nochmal das Empfangsflag testet, d.h. den Interrupt bei Bedarf nochmal ausführt ohne weiteres POP/PUSH.
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.