> Richtige Interrupts, die auch was sinnvolles tun, brauchen mehr als 0
3
> Register und verbiegen mit Sicherheit auch Flags.
4
5
Bei Avrs ist es durchaus möglich Interrupts zu schreiben, die die Flags
6
nicht ändern. Ein FIFO kann beispielsweise so realisiert werden. Dabei
7
spielt besonders die "cpse"-Instruktion eine Rolle, mit der Vergleiche
8
durchgeführt werden können, ohne die Flags zu ändern (so schlau ist der
9
avrgcc allerdings bei Weitem nicht, um solche Interrupts zu generieren).
Meine Frage ist nun: wie müsste eine konkrete Implementierung aussehen?
Es hängt jetzt kein direkter Nutzen dran, es ist eher eine akademische
Frage ;-)
Meine Rahmenbedingungen wären (meiner jetzigen Implementierung folgend):
1
- ein 2^n Ringpuffer
2
-> ein uint8_t Lese-Index
3
-> ein uint8_t Schreib-Index
4
-> ein uint8_t[2^n]-Array für die Daten
5
- die ISR, die den FIFO-Teil enthält (z.B.: ein UART-RX-Interrupt)
6
- von C aus auf die Variablen zugreifen können (am besten sind die Variablen direkt in deklariert)
7
- andere Funktionen in C oder Assembler (dann aber mit avr-gcc-ABI)
8
- ISR in Inline-ASM oder separatem Assembler-File
Beispiel für die Implementierung in C:
1
/* schnell runtergeschrieben; Funktion nicht getestet */
Hi N. G.,
ich verstehe nicht, warum man das in der Realität machen sollte.
Ich schreibe viel AVR Assembler Code in meinen Libs, wenn ich das SREG
in einer Interrupt-Service-Routine sichern und wieder herstellen kann,
dann mache ich das.
Nur künstlich würde ich mich selbst einschränken wollen.
Es mag Sonderfälle geben, da kann es sinnvoll sein seinen etwas anders
aufzuschreiben.
Hochsprache Anweisungen kann man mit etwas Überlegen, fast 1:1 in
Assembler mit einer Macro-Implementierung übersetzen.
Karl M. schrieb:> ich verstehe nicht, warum man das in der Realität machen sollte.
Sehe ich auch so.
Selbst mit doppelter Baudrate hast Du mindestens 80 Zyklen je Interrupt.
Das reicht dicke, um das SREG zu sichern.
Es wäre eine rein akademische Spielerei, sich da unnötig einzuschränken.
schreiben. Der Compiler wird sicher dasselbe / etwas mindest gleich
performantes daraus machen. Aber Vorteil: sollte RX_BUFFER_SIZE mal
keine 2er Potenz sein (implizite Annahme hier), stimmt der Code
trotzdem.
Du schreibst oben: Implementierung in C.
In C++ könnte man mit static_asserts sicherstellen, dass man es nicht
compilieren kann, wenn das keine 2'er Potenz ist. Oder man schafft sich
einen Datentyp, der nur 2er Potenzen als Werte annehmen kann, oder ...
Wilhelm M. schrieb:>> uint8_t uart0_hasData(void) {>> return rx_read_index ^ rx_write_index;>> }>> Du darfst ruhig hier (rx_read_index == rx_write_index) verwenden,
Eher (rx_read_index != rx_write_index)
Hallo !
Peter Dannegger hat in seiner Uart Fifo Implementierung schon das Beste
in C verfasst, welches eine sehr gute Optimierung zulässt.
Beitrag "AVR-GCC: UART mit FIFO"
Also Software Uart mit Fifo:
Beitrag "Software UART mit FIFO"Wilhelm M. schrieb:> In C++ könnte man mit static_asserts sicherstellen, dass man es nicht> compilieren kann, wenn das keine 2'er Potenz ist. Oder man schafft sich> einen Datentyp, der nur 2er Potenzen als Werte annehmen kann, oder ...
Dies ist ein Test, ober die Puffergröße der Regel 2^n genügt:
1
#define buffersize (16) // 2^4 Beispiel
2
if((buffersize&(buffersize-1))==0){// (16 and 15) == 0
Hallo an alle,
ihr hab mich wohl missverstanden:
Ich brauche keine Implementierung in C/C++ oder sonst was
Ich habe kein Zeitproblem oder Ähnliches
Es ging lediglich um die Überprüfung der Aussage aus dem verlinkten
Beitrag.
Wie kann man in Assembler eine Funktion schreiben, die einen Ringpuffer
implementiert, ohne das SREG zu verändern?
Ja, diese Frage ist, wie im Eingangsposting auch schon geschrieben, rein
akademisch!
Aber mich würde halt interessieren, ob es überhaupt möglich wäre.
N.G.
Hallo N. G.,
danke für die Klarstellung, ich hatte gestern Nacht dies versucht,
scheitere aber an der Addition, die als 9Bit immer das Carry beinhaltet.
Ein entrollen einer 8Bit Addition auf 256 Abfragen werden ich nicht
machen.
Karl M. schrieb:> Ein entrollen einer 8Bit Addition auf 256 Abfragen werden ich nicht> machen.
Braucht man eine volle Addition?
Inkrementierung über LD r,rr+ / ST rr+,r, oder Tabelle.
Begrenzung über CPSE oder wrap-around.
Karl M. schrieb:> Dies ist ein Test, ober die Puffergröße der Regel 2^n genügt:>
1
>#definebuffersize(16)// 2^4 Beispiel
2
>if((buffersize&(buffersize-1))==0){// (16 and 15) == 0
3
>// 2^n ok
4
>}
5
>else{
6
>// 2^n fail
7
>}
8
>
Ja super: ein Laufzeittest! Das ist nicht besonder elegant!!! Und was
mache ich, wenn der fehlschlägt? Die rote LED an?
Besser ist, dass das Programm nicht compiliert!
Frank M. schrieb:> Wilhelm M. schrieb:>>> uint8_t uart0_hasData(void) {>>> return rx_read_index ^ rx_write_index;>>> }>>>> Du darfst ruhig hier (rx_read_index == rx_write_index) verwenden,>> Eher (rx_read_index != rx_write_index)
Ups, ja klar. Danke!
Man schreibt ja auch auch nicht:
1
x=x^x;
sondern einfach
1
x=0;
und es ist Aufgabe des Compilers, optimalen Code zur die Zielplattform
zu erzeugen.
N. G. schrieb:> #define RX_BUFFER_SIZE 32>> #if RX_BUFFER_SIZE & (RX_BUFFER_SIZE - 1)> #error "RX Buffer size has to be a power of two"> #endif
War ja schon da, und sollte eigentlich nicht Teil der Diskussion sein
N.G.
Wilhelm M.,
wir schreiben doch hier nur exemplarisch Code.
Ich hätte eine Pseudosprache wählen sollen - Fortran ?
Weiter unten steht es dann auch nochmals anders formuliert.
Wilhelm M. schrieb:> Karl M. schrieb:>>> Dies ist ein Test, ober die Puffergröße der Regel 2^n genügt:>>> #define buffersize (16) // 2^4 Beispiel>> if ( (buffersize & (buffersize - 1)) == 0 ) { // (16 and 15) == 0>> // 2^n ok>> }>> else {>> // 2^n fail>> }>>>> Ja super: ein Laufzeittest! Das ist nicht besonder elegant!!! Und was> mache ich, wenn der fehlschlägt? Die rote LED an?>> Besser ist, dass das Programm nicht compiliert!
N. G. schrieb:> N. G. schrieb:>> #define RX_BUFFER_SIZE 32>>>> #if RX_BUFFER_SIZE & (RX_BUFFER_SIZE - 1)>> #error "RX Buffer size has to be a power of two">> #endif>> War ja schon da, und sollte eigentlich nicht Teil der Diskussion sein
Ah ja, stimmt! Hatte ich übersehen ... danke für den Hinweis.
Allerdings könnte man nach(!) diesem Macro das auch wieder umdefinieren,
z.B. durch eine andere #include-Anweisung ... das ist das Problem von
solchen, un-scoped Textersetzungen ...
Wilhelm M. schrieb:> Allerdings könnte man nach(!) diesem Macro das auch wieder umdefinieren,
Ja, theroretisch kann man viel böse Sachen machen. Aber:
Ich finde, Du übertreibst Deinen missionarischen Eifer etwas. Lass doch
den Leuten, die sich bei C statt C++ wohler fühlen, ihre eigene
Entscheidung für das Tool, das sie möchten.
Du kannst ja gern Beispiele hier und da für die Überlegenheit von C++
gegenüber C anbringen. Aber muss das so weit gehen, dass ich mich immer
an Kreuzzüge erinnert fühle?
Man kann sich sowohl mit C als auch mit C++ in den Fuß schießen. Das ist
wohl unbestritten.
Frank M. schrieb:> Du kannst ja gern Beispiele hier und da für die Überlegenheit von C++> gegenüber C anbringen. Aber muss das so weit gehen, dass ich mich immer> an Kreuzzüge erinnert fühle?
Dann erklär mir mal bitte, was diese Anmerkung von mir
> In C++ könnte man mit static_asserts sicherstellen, dass man es nicht> compilieren kann, wenn das keine 2'er Potenz ist. Oder man schafft sich> einen Datentyp, der nur 2er Potenzen als Werte annehmen kann, oder ...
mit Kreuzzügen zu tun hat.
N. G. schrieb:> Meine Rahmenbedingungen wären (meiner jetzigen Implementierung> folgend):- ein 2^n Ringpuffer> -> ein uint8_t Lese-Index> -> ein uint8_t Schreib-Index> -> ein uint8_t[2^n]-Array für die Daten> - die ISR, die den FIFO-Teil enthält (z.B.: ein UART-RX-Interrupt)> - von C aus auf die Variablen zugreifen können (am besten sind die> Variablen direkt in deklariert)> - andere Funktionen in C oder Assembler (dann aber mit avr-gcc-ABI)> - ISR in Inline-ASM oder separatem Assembler-File
Meiner unmaßgeblichen Meinng nach geht das überhaupt nur mit einem
256Byt großen Buffer, und 8-Bit Index-Zeigern, die halt am Ende
automatisch überlaufen.
Sämtliche Vergleichs- und Logischen Verknüpfungsoperationen sowie alle
Rechenoperationen verändern das SREG, und sind daher nicht einsetzbar.
Oliver
Oliver S. schrieb:> Sämtliche Vergleichs- und Logischen Verknüpfungsoperationen sowie alle> Rechenoperationen verändern das SREG, und sind daher nicht einsetzbar.
Wie schon erwähnt kann man sowohl Inkrementieren als auch auf Gleichheit
testen, ohne Flags in Anspruch nehmen zu müssen.
Ich ignoriere mal Deine ganzen Anforderungen aus dem obersten Posting
und orientiere mich erstmal an
N. G. schrieb:> Die Herausforderung wäre nun, das ganze in der ISR in ASM zu schreiben,> ohne Flags zu verändern.
Wenn's richtig schnell sein soll, dann vielleicht so:
1
.include "m1284pdef.inc"
2
3
rjmp init
4
5
.org URXC0addr
6
rjmp rxint
7
8
init:
9
;setup of USART0 not shown here
10
11
ldi XL,LOW(rxbuf)
12
ldi XH,HIGH(rxbuf)
13
movw YH:YL,XH:XL
14
sei
15
wait:
16
sleep
17
chk_buf:
18
cp XL,YL
19
breq wait
20
ld r16,Y+
21
ldi YH,HIGH(rxbuf)
22
;process received character
23
rjmp chk_buf
24
25
rxint:
26
lds r15,(UDR0)
27
st X+,r15
28
ldi XH,HIGH(rxbuf)
29
reti
30
31
.dseg
32
.org (SRAM_START+$ff)&$100
33
rxbuf: .byte 256
R15 und X sind exklusiv für die ISR reserviert, es werden keine Flags
verändert.
Der Empfangspuffer muß an einer 256-Byte-Grenze liegen, ein Überlauf
wird nicht behandelt.
Je mehr in der ISR noch rumgerödelt werden soll (Überlaufprüfung,
Empfangspuffer kleiner/größer als 256 Byte etc.), desto weniger
wahrscheinlich läßt sich eine Lösung finden, die ohne Einfluß auf die
Flags auskommt.
Wilhelm M. schrieb:> Dann erklär mir mal bitte, was diese Anmerkung von mir>> In C++ könnte man mit static_asserts sicherstellen, dass man es nicht> compilieren kann, wenn das keine 2'er Potenz ist. Oder man schafft sich> einen Datentyp, der nur 2er Potenzen als Werte annehmen kann, oder ...>> mit Kreuzzügen zu tun hat.
Dann erklär mit bitte, warum Du obiges Zitat aufführst, wenn ich mich
doch tatsächlich auf dieses
Wilhelm M. schrieb:> Allerdings könnte man nach(!) diesem Macro das auch wieder umdefinieren,> z.B. durch eine andere #include-Anweisung ... das ist das Problem von> solchen, un-scoped Textersetzungen ...
in meinem Beitrag bezogen habe.
Du suggerierst mit beiden Aussagen zusammen:
- C++ ist gut, denn mit static_asserts kann man sicherstellen,
dass auch dümmste Programmierer darauf hingewiesen werden, dass
die 42 doch keine Zweierpotenz ist.
- C ist böse, denn durch Umdefinition von Macros (dummer Programmierer
wird zum bösen Programmierer) kann der Programmierer nicht vor
seinem Irrglauben geschützt werden, die 42 wäre tatsächlich
eine Zweierpotenz.
Ist ja alles schön und gut. Ich verstehe ja auch Deine Intention. Aber
wenn man suggeriert bekommt, C++ müsse mich vor meinen eigenen
Dummheiten schützen, dann ist es nicht sehr angenehm, dass ich als Leser
Deiner Beiträge pauschal als zu beschützendes Dummchen abgestempelt
werden, nur weil ich mich mit C wohler als mit C++ fühle.
Es ging mir auch nicht konkret um diesen Beitrag, sondern eher um den
allgemeinen Eindruck, den ich während der letzten Tage/Wochen bekam.
Dein geschickt eingefädelter "Programmierwettbewerb", der von vornherein
nur deshalb veranstaltet wurde, um die Überlegenheit von C++ zu
demonstrieren, obwohl er unter dem Vorwand eines real existierenden
Zeitproblems gepostet wurde, ist mir da noch unangenehm in Erinnerung.
Ich mag solche Spielchen einfach nicht. Aber das ist meine persönliche
Meinung.
P.S.
Es gibt auch effiziente Ringbuffer-Implementationen, die solche
Optimierungen bzgl. Bufferlänge = Zweierpotenz gar nicht brauchen.
Frank M. schrieb:> Wilhelm M. schrieb:>> Dann erklär mir mal bitte, was diese Anmerkung von mir>>>> In C++ könnte man mit static_asserts sicherstellen, dass man es nicht>> compilieren kann, wenn das keine 2'er Potenz ist. Oder man schafft sich>> einen Datentyp, der nur 2er Potenzen als Werte annehmen kann, oder ...>>>> mit Kreuzzügen zu tun hat.>> Dann erklär mit bitte, warum Du obiges Zitat aufführst, wenn ich mich> doch tatsächlich auf dieses>> Wilhelm M. schrieb:>> Allerdings könnte man nach(!) diesem Macro das auch wieder umdefinieren,>> z.B. durch eine andere #include-Anweisung ... das ist das Problem von>> solchen, un-scoped Textersetzungen ...
Auch hier kann ich keinen Kreuzzug erkennen. Wie hättest Du denn gerne
so einen Hinweis formuliert? Verzeihung Hochwürden, ich bitte
untertänigst um Redeerlaubnis?
Deine Wortwahl ist absolut unpassend. Es ist ja schon sehr erschreckend,
welche Wortwahl hier manche andere an den Tat legen, aber das so etwas
von einem Moderator kommt, ist wirklich vollkommen unpassend.
> Du suggerierst mit beiden Aussagen zusammen:>> - C++ ist gut, denn mit static_asserts kann man sicherstellen,> dass auch dümmste Programmierer darauf hingewiesen werden, dass> die 42 doch keine Zweierpotenz ist.
Nein, C++ ist in diesem(!) Fall besser.
> - C ist böse, denn durch Umdefinition von Macros (dummer Programmierer> wird zum bösen Programmierer) kann der Programmierer nicht vor> seinem Irrglauben geschützt werden, die 42 wäre tatsächlich> eine Zweierpotenz.
Nein, C ist in diesem(!) Fall schlechter.
> Aber> wenn man suggeriert bekommt, C++ müsse mich vor meinen eigenen> Dummheiten schützen,
Genau das ist es. Als erfahrener Programmierer wirst Du das wissen.
> dann ist es nicht sehr angenehm, dass ich als Leser> Deiner Beiträge pauschal als zu beschützendes Dummchen abgestempelt> werden, nur weil ich mich mit C wohler als mit C++ fühle.
Wenn Du meine Beiträge lesen würdest als das, was sie sind, würdest Du
bemerken, dass ich Leuten, die ihr C mögen, den Spaß lasse. Allerdings
darf man in einer aufgeklärten Welt auf Alternativen hinweisen.
Zudem weise ich sehr oft darauf hin, dass m.E. eine gute Strategie auch
für die C-affinen ist, sich einige Rosinen aus dem C++ Kuchen heraus zu
picken.
Leider muss ich sehr oft feststellen, dass man als jemand, der
Alternativen aufzeigt, hier oftmals direkt schimpft wird.
> Es ging mir auch nicht konkret um diesen Beitrag, sondern eher um den> allgemeinen Eindruck, den ich während der letzten Tage/Wochen bekam.> Dein geschickt eingefädelter "Programmierwettbewerb", der von vornherein> nur deshalb veranstaltet wurde, um die Überlegenheit von C++ zu> demonstrieren, obwohl er unter dem Vorwand eines real existierenden> Zeitproblems gepostet wurde, ist mir da noch unangenehm in Erinnerung.
Wenn Du das so meinst, dann solltest Du diesen Programmierwettbewerb
hier auch als solchen bezeichnen!!!
N. G. schrieb:> Die Herausforderung wäre nun, das ganze in der ISR in ASM zu schreiben,> ohne Flags zu verändern.
Eine der unvermeidlichen Nebenwirkungen ist, das der nächste
Programmierer, der den Code bearbeitet (z.B. du selbst im nächsten
Jahr), sich auch daran halten muß, sonst gehts schief. Ich würde mir da
nicht trauen.
MfG Klaus
Wilhelm M. schrieb:> Deine Wortwahl ist absolut unpassend. Es ist ja schon sehr erschreckend,> welche Wortwahl hier manche andere an den Tat legen, aber das so etwas> von einem Moderator kommt, ist wirklich vollkommen unpassend.
Auch ich bewege mich in diesem Forum vornehmlich als normaler
Forumsanwender. Den Titel "Moderator" kann ich bei dem Verfassen eines
Beitrags leider nicht von Fall zu Fall einfach löschen oder erscheinen
lassen.
> Wenn Du das so meinst, dann solltest Du diesen Programmierwettbewerb> hier auch als solchen bezeichnen!!!
Um Missverständnissen vorzubeugen: Es ging mir dabei um diesen Thread:
Beitrag "Assembler (AVR) Freaks bitte: der schnellste Weg, einen ganzzahligen Wert zu skalieren?"
und nicht um diesen hier. Und damit ist für mich nun EOD.
Frank M. schrieb:> Wilhelm M. schrieb:>> Deine Wortwahl ist absolut unpassend. Es ist ja schon sehr erschreckend,>> welche Wortwahl hier manche andere an den Tat legen, aber das so etwas>> von einem Moderator kommt, ist wirklich vollkommen unpassend.>> Auch ich bewege mich in diesem Forum vornehmlich als normaler> Forumsanwender. Den Titel "Moderator" kann ich bei dem Verfassen eines> Beitrags leider nicht von Fall zu Fall einfach löschen oder erscheinen> lassen.
Was heißt hier leider!?! Auch von einem Moderator erwarte ich
Aufrichtigkeit!
>>> Wenn Du das so meinst, dann solltest Du diesen Programmierwettbewerb>> hier auch als solchen bezeichnen!!!>> Um Missverständnissen vorzubeugen: Es ging mir dabei um diesen Thread:>> Beitrag "Assembler (AVR) Freaks bitte: der schnellste Weg, einen ganzzahligen Wert zu skalieren?">> und nicht um diesen hier.
Das weiß ich schon, und dieser Thread hier, den ich auch sehr
interessant finde und gar nicht anstößig, ist in seiner Qualität
dasselbe mit einer anderen Fragestellung: die Bitte, um eine möglichst
gute Lösung eines Problems ausserhalb des persönlichen
Erfahrungshorizonts.
Ziemlich akademischen Problem das...
Man hat folgende Instruktionen zur Verdügung:
== Load Store ==
LD*, ST*, LPM, IN, OUT, SBI, CBI, PUSH, POP
== Arithmetik ==
LDI, SWAP
== Vergleiche ==
CPSE, SBRC, SBRS
== Sprung ==
[R]JMP, [R]CALL, [E]IJMP, [E]ICALL, RET
* Branches sind witzlos, da die vorheriges Setzen von SREG erfordern.
* BLD ist witzlos da es vorheriges BST erfordert.
* Addition von 1 könnte man per LPM Z+ realisieren falls unterstützt.
Viel Spaß...
Für solche Spielereien ist der 8051 viel besser geeignet. Der hat nur
wenige Instruktionen, die das PSW ändern:
ADD, ADDC, DA, SUBB, MUL, DIV, RRC, RLC, CJNE und die Bitoperationen mit
C als Ziel.
Hallo @all,
ich habe mich nochmal ein- bis zwei Stunden hingehockt und es probiert,
aber ich bin auf keinen grünen Zweig gekommen. Ich muss aber zugeben,
dass ich absolut schlecht in ASM bin.
Aber danke für eure Beiträge!
Mit freundlichen Grüßen,
N.G.
Das geht schon ohne Veränderung des SREG, allerdings ist das halt
insofern dann doch völlig sinnlos, als daß es nicht ohne Nutzung und
damit Sicherung einiger Register geht.
Oliver
Oliver S. schrieb:> Das geht schon ohne Veränderung des SREG, allerdings ist das halt> insofern dann doch völlig sinnlos, als daß es nicht ohne Nutzung und> damit Sicherung einiger Register geht.
Genau das ist der idiotische Trugschluss, dem C-Programmierer immer
wieder unterliegen. Nein, die Benutzung von Registern in ISRs impliziert
natürlich nicht automatisch, dass sie in jeder ISR-Instanz gerettet und
restauriert werden müssen. Man muß einfach nur (durch Konvention) diese
Register exklusiv für diesen Job freistellen (und ggf. mit geeigneten
Defaultwerten belegen, bevor das Interruptmassaker beginnt).
Das hört sich nach performancemindernder Registerverschwendung an, ist
aber in der Praxis in aller Regel das genaue Gegenteil, nämlich die
performancefördernste Maßnahme überhaupt, das gilt mit zunehmender
Interruptrate natürlich in immer größerem Maße...
Nur leider kommen C-Nutzer kaum in die Verlegenheit, die Vorteile so
eines Konzeptes zu nutzen, weil ihre grenzdebilen Compiler das nur sehr
eingeschränkt bis garnicht unterstützen, jedenfalls für die
AVR-Architektur...
In anderen Architekturen ist das absoluter Usus, wenn auch auf einem
anderen Weg, der es den Compilerfricklern etwas einfacher macht: Es gibt
dort einfach alle Register in mehrfacher Ausführung und es wird bei
einem Interrupt zwischen diesen Registersätzen umgeschaltet. Oder eine
Variante dieses Grundprinzips...
Wichtig scheint irgendwie nur zu sein, den zur masslosen Überschätzung
der Bedeutung ihrer Programmiersprache neigenden Compilerprogrammierern
das Gefühl zu geben, sie hätten alle Register der Maschine im
ausschließlichen Besitz ihrer Runtime, denn darauf scheinen sie
irgendwie Wert zu legen. Dabei sind die Engines in aller Regel durchaus
so konstruiert, dass sie problemlos auf ein paar Register verzichten
könnten (klar: natürlich mit Performanceverlust in speicherlastigen
Programmteilen), aber irgendwie wollen diese Wichser es nicht, dass der
User ihrer Werke daraus Vorteile ziehen darf. Selbst wenn die
Möglichkeit prinzipiell bis in's Frontend hinein besteht, ist sie
zumindest nur lausig bis garnicht dokumentiert, so dass sie wirklich nur
für absolute Insider nutzbar wird...
Da kann man dann besser gleich komplett in Assembler programmieren. Da
hat man die Freiheit, die Register sinnvoll einzusetzen, von
vornherein...
Den Thread hab ich erst jetzt gesehen. Die Aussage kommt noch aus meiner
AVR-Assemblerzeit, in der ich tatsächlich ähnlichen Code hatte. Ohne
diesen zu suchen, kann man das Problem folgermaßen lösen:
1
; load fifo pointer
2
lds XH, hi8(fifo_ptr)
3
lds HL, lo8(fifo_ptr)
4
5
; read byte
6
ld temp, X+
7
8
; bound checking
9
ldi temp, lo8(fifo_end)
10
cpse XL, temp
11
rjmp store
12
13
; reset fifo pointer
14
ldi XL, lo8(fifo_start)
15
ldi XH, hi8(fifo_start)
16
17
store:
18
sts hi8(fifo_ptr), XH
19
sts lo8(fifo_ptr), XL
20
21
reti
Das ganze funktioniert bis Puffergrößen von 256 Byte, wobei 256 Byte wie
oben schon angemerkt einfacher zu realisieren sind. Die drei benutzten
Register müssen natürlich gesichert werden, aber das muss man sowieso.
Wenn das FIFO im Speichern an bestimmte Adressen gelegt werden kann,
kann soagr noch etwas optimiert werden. Ob das Sinn macht oder nicht,
darf jeder selbst für sich entscheiden. Ich hatte damals meinen Spaß
daran.
c-hater schrieb:> Man muß einfach nur (durch Konvention) diese> Register exklusiv für diesen Job freistellen (und ggf. mit geeigneten> Defaultwerten belegen, bevor das Interruptmassaker beginnt).
Selbst der größte c-hater sollte allerdings verstehen, das das im Fall
der x- und y-Register auf dem AVR, um den es hier geht, praktisch nicht
möglich ist.
Oliver
c-hater schrieb:> Wichtig scheint irgendwie nur zu sein, den zur masslosen Überschätzung> der Bedeutung ihrer Programmiersprache neigenden Compilerprogrammierern> das Gefühl zu geben, sie hätten alle Register der Maschine im> ausschließlichen Besitz ihrer Runtime, denn darauf scheinen sie> irgendwie Wert zu legen. Dabei sind die Engines in aller Regel durchaus> so konstruiert, dass sie problemlos auf ein paar Register verzichten> könnten
warum haben "die Wichser" beim gcc dann -ffixed-<register> erfunden?
c-hater schrieb:> ...
ha ha
Unser c-hater ist auch schon wach, sitzt wieder mit puterrotem Kopf,
geplatzem Kragen und 220 Blutdruck vor'm Rechner und kloppt seine c-hate
rein.
Ein Tag ohne c-hate ist ein verlorener Tag! Armer Wicht.
Vielleicht ersma zur nächsten Apotheke um die Blutdruck-Pillen
aufzustocken... die sind beim c-hater schneller zu Ende als er denkt.
c-hater hat insoweit recht, als nicht jeder µC und nicht jede Sprache
für jeden Zweck taugt. Wenn man also extreme Anforderungen in
Reaktionszeit auf Ereignisse hat, dann ist nicht jede Plattform
geeignet.
Vielleicht helfen dann seine µCs mit umschaltbaren Registersätzen
weiter, aber im Grunde ist das auch nur eine Zwischenlösung, die ein
Bisschen was bringt. Denn jenseits davon lauert die konfigurierbare
Hardware, die noch viel viel reaktionsfähiger ist als jeder µC.
Also müsste er in diesem Sinn nicht nur C hassen, und mangels adäquater
Registerstruktur die AVRs gleich mit, sondern auch interruptfreudigere
Prozessoren und sowieso sämtliche sequentielle Programmierung in Form
von Prozessoren. Und alles ausser FPGAs schon vorneweg ablehnen.
Apropos: Kann man mit FPGAs eigentlich auf Bitebene entwickeln? Denn
VHDL ist doch auch bloss eine fürchterliche und bestimmt verlustreiche
Hochsprache. ;-)