Hallo, habe jetzt doch Bedarf an einem Interrupt-gesteuerten System (basteln) und habe verstanden, dass der/die AVR immer nur einen Interrupt abarbeiten. Wenn während einer laufenden Interrupt-Routine weitere Interrupts auftreten, dann werden die aber nicht verworfen, sondern offensichtlich gespeichert. Und nun verstehe ich die Doc's (auch hier im ".net") nicht. Ist es so, dass gleich nach dem RETI der ersten Unterbrechung der nächste Interrupt ausgelöst wird? Oder muß ich da noch was verwalten?? Und weitere Frage, macht es einen Unterschied, ob der nächste Interrupt ein Externer oder ein Interner ist? Würde mich über eine erhellende Antwort freuen. Danke und Gruß, Rainer PS: dabei kommt mir noch die Frage, wieviele Interrupts die AVR denn überhaupt schachteln können...
:
Gesperrt durch Moderator
Rainer V. schrieb: > Hallo, habe jetzt doch Bedarf an einem Interrupt-gesteuerten System > (basteln) und habe verstanden, dass der/die AVR immer nur einen > Interrupt abarbeiten. Das machen andere Prozessoren eben so, denn sie haben nur eine CPU. Was du meinst ist die Unterbrechung von Interrupts durch höher priorisierte Interrupts. Das kann der AVR von hause aus nicht. > Wenn während einer laufenden Interrupt-Routine > weitere Interrupts auftreten, dann werden die aber nicht verworfen, > sondern offensichtlich gespeichert. Ja. Aber nur 1 von jeder Sorte. Kommen in der zeit mehr, geht einer verloren, siehe Interrupt. > Und nun verstehe ich die Doc's (auch > hier im ".net") nicht. Ist es so, dass gleich nach dem RETI der ersten > Unterbrechung der nächste Interrupt ausgelöst wird? Ja. > Oder muß ich da noch > was verwalten?? Nö. Die CPU bearbeitet maximal 1 ASM-Befehl. > Und weitere Frage, macht es einen Unterschied, ob der > nächste Interrupt ein Externer oder ein Interner ist? Nö. > PS: dabei kommt mir noch die Frage, wieviele Interrupts die AVR denn > überhaupt schachteln können... Vnn Haus aus gar keinen. Per Software soviel wie du willst (oder der Stack überläuft)
Rainer V. schrieb: > Hallo, habe jetzt doch Bedarf an einem Interrupt-gesteuerten System > (basteln) und habe verstanden, dass der/die AVR immer nur einen > Interrupt abarbeiten. Nicht unbedingt. Man kann in einer ISR auch Interrupts wieder einschalten, dann kann sie durch andere ISRs unterbrochen werden. Man sollte sich nur sehr gut überlegen, ob man das wirklich braucht. > Wenn während einer laufenden Interrupt-Routine weitere Interrupts auftreten, > dann werden die aber nicht verworfen, sondern offensichtlich gespeichert. So ähnlich. Ein Auftreten der Interrupt-Bedingung setzt das dazugehörige Interrupt-Flag. Sonst passiert in dem Moment erstmal nichts. > Und nun verstehe ich die Doc's (auch hier im ".net") nicht. Ist es so, dass > gleich nach dem RETI der ersten Unterbrechung der nächste Interrupt > ausgelöst wird? Oder muß ich da noch was verwalten?? Nach jeder Instruktion prüft der AVR die Flags. Wenn für einen bestimmten Interrupt sowohl dessen Interrupt-Flag, als auch sein Interrupt-Enable-Flag und das globale Interrupt-Enable gesetzt ist, wird der Eintrag in der Interrupt-Vektor-Tabelle angesprungen. Wenn zu diesem Zeitpunkt mehrere Interrupts gleichzeitig anstehen, wir der Eintrag mit der niedrigsten Adresse genommen. Da beim Einsprung in eine ISR das globale Interrupt-Enable automatisch gelöscht wird, kann sie per Default nicht durch einen anderen Interrupt unterbrochen werden. Wenn aber ein anderer Interrupt auftritt, wird dessen Interrupt-Flag gesetzt, und sobald aus der gerade laufenden ISR rausgesprungen wird, wird auch das globale Interrupt-Flag gesetzt, und es wird dann der Interrupt-Vektor des neuen Interrupts angesprungen. > Und weitere Frage, macht es einen Unterschied, ob der nächste Interrupt ein > Externer oder ein Interner ist? Würde mich über eine erhellende Antwort freuen. Was verstehst du darunter? Interrupt ist Interrupt, egal ob der von einem Interrupt-Pin, einem Timer oder einem UART ausgelöst wird. > Danke und Gruß, Rainer PS: dabei kommt mir noch die Frage, wieviele > Interrupts die AVR denn überhaupt schachteln können... Bis der Stack ausgeht.
:
Bearbeitet durch User
Eine Interruptroutine sollte so kurz wie moeglich sein. also keine Float-exponentiation, keine UART Interaktion, sondern oft nur ein Register lesen, setzen und ein Flag setzen.
Pandur S. schrieb: > Eine Interruptroutine sollte so kurz wie moeglich sein. also keine > Float-exponentiation, keine UART Interaktion, Soso, gilt das auch für die UART-Interrupts? ;-) > sondern oft nur ein > Register lesen, setzen und ein Flag setzen. Quark. Man kann schon ne ganze Menge mehr in einem Interrupt machen, wenn man weiß was man tut. Wenn ein Timer-Interrupt nur alle 10ms auftritt darf man in diesem auch mal 5ms was machen, WENN nicht andere, wichtige Interrupts auch noch aktiv sind!
Hallo, ich finde auf der Seite http://weigu.lu/tutorials/avr_assembler/index.html - Modul B - sind die Interrupts ganz gut beschrieben. Sonst helfen die jeweiligen Datenblätter weiter Gruß Carsten
Rolf M. schrieb: > Da beim Einsprung in eine ISR das globale Interrupt-Enable automatisch > gelöscht wird, kann sie per Default nicht durch einen anderen Interrupt > unterbrochen werden. Wenn aber ein anderer Interrupt auftritt, wird > dessen Interrupt-Flag gesetzt, und sobald aus der gerade laufenden ISR > rausgesprungen wird, wird auch das globale Interrupt-Flag gesetzt, und > es wird dann der Interrupt-Vektor des neuen Interrupts angesprungen. Danke für die Antworten. Ich habe diese hier zitiert, weil sich mir dann die Frage stellt, wenn ich direkt in meiner I-Routine das globale Interrupt-Flag wieder setzte...geht das? Oder stürzt das ab? Und wenn ich es machen könnte, was passiert dann?! Sorry, aber ich versuche ein Gefühl für Interrupts zu bekommen...ja klar, könnte auch einfach mal machen...aber es sollten doch einige Fundamentals bei mir klar sein. Danke und GRuß Rainer
Rainer V. schrieb: > Danke für die Antworten. Ich habe diese hier zitiert, weil sich mir dann > die Frage stellt, wenn ich direkt in meiner I-Routine das globale > Interrupt-Flag wieder setzte...geht das? Es geht. Damit kannst du verschachtelte Interrupts erlauben. > Oder stürzt das ab? Und wenn > ich es machen könnte, was passiert dann?! Es passiert nichts, solange nicht so viele Interrupts verschachtelt aufgerufen werden bis der Stack voll ist. D.h. man kann es machen, aber man sollte wissen was man tut
Cyblord -. schrieb: > Es geht. Damit kannst du verschachtelte Interrupts erlauben. Danke...also nur für mein Verständnis...es kommt ein Int und die CPU rettet die nächste Adresse (aus der Hauptroutine) auf den Stack und springt in die Int-Routine. Wenn ich dort sofort wieder Interrupt erlaube und der kommt, dann landet die nächste Adresse (aus der Int-Routine) auf dem Stack und die neue Int-Routine wird abgearbeitet. Deren RETI führt dann zurück in die vorherige Interrupt-Routine. Richtig??? Es ist nicht leicht :-) Gruß Rainer
Rainer V. schrieb: > Hallo, habe jetzt doch Bedarf an einem Interrupt-gesteuerten System > (basteln) und habe verstanden, dass der/die AVR immer nur einen > Interrupt abarbeiten. Wie meinst du das? Je nachdem, wie du es programmiert hast, kann eine laufende Interrupt-Routine natürlich auch von einem anderen Interrupt unterbrochen werden, so dass die Abarbeitung dazwischen geschoben wird. Das kommt immer drauf an, ob Interrupts freigegeben worden sind.
Rainer V. schrieb: > Wenn ich dort sofort wieder Interrupt > erlaube und der kommt, dann landet die nächste Adresse (aus der > Int-Routine) auf dem Stack und die neue Int-Routine wird abgearbeitet. > Deren RETI führt dann zurück in die vorherige Interrupt-Routine. Ja, genau wie bei verschachtelten Funktionsaufrufen.
Du musst nix verwalten, aber EIN Befehl im "normalen Ablauf" wird nach RETI ausgeführt, bevor die nächste "gespeicherte" Interruptanforderung bedient wird. - When the AVR exits from an interrupt, it will always return to the - main program and execute one more instruction before any pending - interrupt is served. Externe -, oder interne Interruptanforderung ist "wurscht". Der entscheidende Unterschied ist, ob er durch ein Ereignis (wenig Probleme) ausgelöst wird, oder durch einen Zustand (kann Probleme machen). Die Möglichkeit, den externen INT0, oder INT1 mit Low-Pegel (!) zu triggern, halte ich für eine dumme Sache, wenn ich keine SICHERE Möglichkeit habe, vom µC aus wieder auf High-Pegel zu schalten... Der Rest ist: Grundregeln für Interrupts beachten und ERFAHRUNGEN SAMMELN!
Jacko schrieb: > Die Möglichkeit, den externen INT0, oder INT1 mit Low-Pegel (!) zu > triggern, halte ich für eine dumme Sache, wenn ich keine SICHERE > Möglichkeit habe, vom µC aus wieder auf High-Pegel zu schalten... Richtig dumm wird es erst, wenn man in so einem Fall in der Interruptroutine die Interrupts wieder frei gibt ...
Rainer V. schrieb: > Wenn während einer laufenden Interrupt-Routine > weitere Interrupts auftreten, dann werden die aber nicht verworfen, > sondern offensichtlich gespeichert. Nur wenn das I-Flag im SREG nicht gesetzt ist, was default ist. Falls in der ISR eine SEI Instruktion ausgeführt wird bzw. SREG entsprechend gesetzt wird, kann eine ISR auch unterbrochen werden. Auch von "sich selbst". > Ist es so, dass gleich nach dem RETI der ersten > Unterbrechung der nächste Interrupt ausgelöst wird? Nein, es wird immer zuerst noch eine nicht-ISR Instruktion ausgeführt bevor die nächste anstehende IRQ triggert. Es kommt also zu einer nicht maskierbaren Priority Inversion. In einem sicherheitskritischen OS wäre das nicht so toll... Marssonden sind desalb m.W. aber noch nicht abgestürzt. > Oder muß ich da noch was verwalten?? Nein, die entsprechende IRQ muss aktiviert sein, und IRQs müssen global aktiviert sein. > Und weitere Frage, macht es einen Unterschied, ob der > nächste Interrupt ein Externer oder ein Interner ist? Stehen mehrere IRQs gleichzeitig an, wird die mit der höchsten Priorität (der kleinsten Vector-Nummer) zuerst ausgelöst. > PS: dabei kommt mir noch die Frage, wieviele Interrupts die AVR denn > überhaupt schachteln können... Bis der Platz auf dem Stack aus ist; bzw. bis der Stack in den anders genutzten Speicher bzw. Adressbereich hineinwächst: Heap, Static Storage, I/O-Bereich, ...
Falk B. schrieb: > Wenn ein Timer-Interrupt nur alle 10ms > auftritt darf man in diesem auch mal 5ms was machen z.b. IRMP abfragen, mache ich seit Jahren so. ukw hat die IRMP IRQ auch sehr sehr kurz gehalten meine letzte Messung ist lange her mit einer alten Version, 1,5µs und die stören im 10ms Timer IRQ nicht die Bohne, sogar im TIMER IRQ kann ich i2c lesen aus einem PCF8574(a)
Rainer V. schrieb: > Ich habe diese hier zitiert, weil sich mir dann > die Frage stellt, wenn ich direkt in meiner I-Routine das globale > Interrupt-Flag wieder setzte...geht das? Ja. > Oder stürzt das an? Nein. > Und wenn ich es machen könnte, was passiert dann?! Das, was ich beschrieben habe. Es wird nach jeder Instruktion geprüft, ob irgendein Interrupt-Flag und das dazugehörige Interupt-Enable-Flag (und eben das globale) gesetzt ist, und wenn ja, wird der entsprechende Interruptvektor angesprungen. Für den Prozessor spielt es da keine Rolle, ob du gerade in einer ISR bist oder nicht. Der geht nicht in einen speziellen Zustand oder sowas, sondern führt einfach eine Instruktion nach der anderen aus, wie sonst auch. > Sorry, aber ich versuche ein Gefühl für Interrupts zu bekommen... Ja, und man denkt da oft zu kompliziert. Gerade beim AVR ist es eigentlich sehr einfach, aber es muss halt mal "klick" machen. Falk B. schrieb: > Pandur S. schrieb: >> Eine Interruptroutine sollte so kurz wie moeglich sein. also keine >> Float-exponentiation, keine UART Interaktion, > > Soso, gilt das auch für die UART-Interrupts? ;-) Ich vermute, gemeint ist, dass man keine Debug-Prints per UART aus der ISR heraus machen sollte oder irgendwelche Protokolle mit Handshake. Halt nix, wo man erst auf den Abschluss einer Übertragung warten muss. >> sondern oft nur ein >> Register lesen, setzen und ein Flag setzen. > > Quark. Man kann schon ne ganze Menge mehr in einem Interrupt machen, > wenn man weiß was man tut. Es ist aber eher selten nötig, und wenn man es vermeidet, ist man bezüglich späterer Erweiterungen in der Regel flexibler. > Wenn ein Timer-Interrupt nur alle 10ms auftritt darf man in diesem auch > mal 5ms was machen, WENN nicht andere, wichtige Interrupts auch noch > aktiv sind! Und auch das Hauptprogramm mal für 5 ms am Stück unterbrochen werden darf.
Johann L. schrieb: > Bis der Platz auf dem Stack aus ist; bzw. bis der Stack in den anders > genutzten Speicher bzw. Adressbereich hineinwächst: Heap, Static > Storage, I/O-Bereich, ... OK, habe ich jetzt etwas verstanden. Also eine Interrupt-R kann unterbrochen werden, wenn dort sofort das Interrupt-Enable gesetzt wird. Ich muß also nachhalten, wann, wo ,welche Routine aktiviert wurde. Scheint mir erst mal nicht trivial (und ich hoffe doch stark, dass im Weltraum keine AVR's werkeln :-) OK, ich mache mir mal Gedanken, wie man das implementieren würde! Meine konkrete Anwendung besteht aus mehrenen Arduino-Nano, die jeweils von mehreren "Unter-Nanos" Daten bekommen. Die Nanos mit den "Unter-Nanos dran" spreche ich von "Hauptnanos" an und diese Anfrage soll nicht "nachrangig" beantwortet werden. Ich habe also das Problem, dass sowohl ein "untergeordneter" Sender einen Nano anspricht, obwohl der arbeitet, und auch der Master eine Anfrage gleichzeitig schickt. Ich weiß, dass man das durch eine "rigerose Hirarchie" in den Griff bekommen kann, aber ich möchte nicht alle möglichen Sender pausenlos ins Nivana senden lassen. Vielleicht ist diese Beschreibung auch zu unverständlich...ich bitte um Nachsicht... Gruß Rainer
Rainer V. schrieb: > Meine konkrete Anwendung besteht aus mehrenen Arduino-Nano, die jeweils > von mehreren "Unter-Nanos" Daten bekommen. Die Nanos mit den > "Unter-Nanos dran" spreche ich von "Hauptnanos" an und diese Anfrage > soll nicht "nachrangig" beantwortet werden. Das ist ein total komplexes System und kein Anfängerprojekt. In der Realität nimmt man für solche Sachen recht komplexe Netzwerkprotokolle oder Feldbusse her.
Cyblord -. schrieb: > Das ist ein total komplexes System und kein Anfängerprojekt. > In der Realität nimmt man für solche Sachen recht komplexe > Netzwerkprotokolle oder Feldbusse her. Hallo, ja, das weiß ich, auch weil ich nicht wirklich Anfänger bin (trotzdem aber Bastler). Aber vor Int habe ich mich bisher eben gedrückt! Bis zu einem bestimmten Punkt gehts auch ohne...und die Herausforderung für meinen bescheidenen Rahmen ist für mich ok. Habe früher beruflich mit diesen Sachen zu tun gehabt und ehrlich, bis ich ein Ethernet, ein Profibus, ein COM-Net und was auch immer, dazu bekomme, zusammenzuspielen, zumal ich auf der Controllerseite sitze...niemals wäre ein Raumschiff in den Orbiter gekommen... Gruß Rainer
Rainer V. schrieb: > Meine konkrete Anwendung besteht aus mehrenen Arduino-Nano, die jeweils > von mehreren "Unter-Nanos" Daten bekommen. Die Nanos mit den > "Unter-Nanos dran" spreche ich von "Hauptnanos" an und diese Anfrage > soll nicht "nachrangig" beantwortet werden. Ich habe also das Problem, > dass sowohl ein "untergeordneter" Sender einen Nano anspricht, obwohl > der arbeitet, und auch der Master eine Anfrage gleichzeitig schickt. Ich > weiß, dass man das durch eine "rigerose Hirarchie" in den Griff bekommen > kann, aber ich möchte nicht alle möglichen Sender pausenlos ins Nivana > senden lassen. Wenn die Daten erst über 2 Signalwege müssen kann die Anforderung an die Reaktionszeit nicht so sehr hoch sein, soll aber dennoch zügig stattfinden, denke ich. Ich weiß nicht wie du die Kommunikation untereinander aufbaust, wenn du nicht in ein Master Slave Problem inkl. Kollisionserkennung reinrutschen möchtest, dann lasse immer den "Master" den/die Slaves abfragen. Der "Slave" darf nicht von selbst irgendwelche Daten senden. Dann kannste vielleicht folgendes machen. Die "normalen Nanos" sind jeweils die Master für ihre Unter-Nanos (Slaves). Diese Master fragen der Reihe nach im Kreis ihre Slaves zyklisch nach neuen Daten ab und erhalten sie auch. Dein Haupt-Nano ist der Master für die "normalen Nanos", seine Slaves wiederum. Auch hier lässt du den Master zyklisch oder bei Bedarf der Reihe nach seine Slaves ("normalen Nanos") abfragen. Jetzt ist die Frage bei dir, die du dir stellen musst folgende. Sollen die Master<>Slaves jeweils getrennte Busse haben, sodass diese jederzeit unabhängig vom übergeordneten Master mit ihren Slaves kommunizieren können. Oder sollen die alle an einem Bus hängen und der Haupt-Nano redet darauf nur mit den normalen Nanos und der mit den Unter-Nanos. Wobei dann letzteres keinen großen Sinn macht. Dann kann der Haupt-Nano auch gleich mit allen reden. Wenn doch mit einem Bus gedacht, dann behalte das Prinzip bei. Nur der Master quatscht den Slave an und wartet auf Antwort. Der angesprochene Slave ist dann Master und quatscht seinen Slave an. Der Slave antwortet seinem Master und der antwortet wieder als Slave seinem Master. Wenn die Antwort rückwärts erfolgt ist, fragen der Haupt-Master seinen nächsten Slave ab. Dabei ist jederzeit klar, wer fragt und antworten muss. Wichtig ist ein sauberes Protokoll für die Kommunikation zu erstellen. Der Hardwareaufbau ist dabei das geringste Problem. :-)
:
Bearbeitet durch User
>Wichtig ist ein sauberes Protokoll für die Kommunikation zu erstellen.
Und sowas soll Spaß machen?
Planen, entwerfen und dieser ganze Nonsens ist was für nachdenkliche
Typen und verkopfte Theoretiker - kurz Loser. Für solche
Langweiligkeiten sollte einem die Zeit zu schade sein. Die investiert
man besser in das Schreiben von Programmcode. Was soll schon
schiefgehen? Man kann doch alles zu jeder Zeit wieder ändern! Also kommt
man auch so zum Ziel. Einfach mal machen ist das Motto der Winner, oder
erzähl ich hier Blödsinn? Ruhig auch mal als Noch-Nicht-so-Erfahrener an
was Schwieriges wagen, das zeugt von Mut und von der Bereitschaft, an
solchen Aufgaben zu wachsen.
Logo, dass es mal hier oder da hakt, aber dafür gibts Lösungen. Den
Debugger zum Beispiel. Oder den Watchdog. Oder man ersetzt den
Controller durch einen anderen, wenn nur noch ein Hardwarefehler als
Ursache in Frage kommt. In Internetforen kann man Experten um Rat
bitten. Wenn das alles aber nicht geholfen hat, dann sollte man wirklich
das Interrupt Enable in allen Interrupts setzen. Kommt einer
Verdoppelung der Controllerleistung gleich. Gratis! Somit praktisch
garantiert, dass es danach reibungslos läuft.
Ja, das sind die Tricks, die den Profi zum Profi machen. Jetzt weißt Du
Bescheid. Leg los. Viel Erfolg.
Rainer V. schrieb: > Hallo, ja, das weiß ich, auch weil ich nicht wirklich Anfänger bin > (trotzdem aber Bastler). Aber vor Int habe ich mich bisher eben > gedrückt! Bis zu einem bestimmten Punkt gehts auch ohne...und die > Herausforderung für meinen bescheidenen Rahmen ist für mich ok. Habe > früher beruflich mit diesen Sachen zu tun gehabt und ehrlich, bis ich > ein Ethernet, ein Profibus, ein COM-Net und was auch immer, dazu > bekomme, zusammenzuspielen, zumal ich auf der Controllerseite > sitze...niemals wäre ein Raumschiff in den Orbiter gekommen... > Gruß Rainer Evt. reicht auch schon sowas wie CAN oder LIN. Aber irgendein Protokoll on Top brauchst du trotzdem noch. Aber man sollte ich bei vielen Controller, und SubControllern schon mal schauen wie es andere machen und grade in Fahr- oder Flugzeugen gibt es diese Situation. Und die Antwort sind eben Busse wie CAN, LIN, Flexray oder AIRINC. Zunehmend auch Ethernet, aber das muss für dich ja nicht sein. Ich behaupte, ohne eine Strukturierte Kommunikation kommt man nicht ans Ziel. Einfach hier und da mal irgendwas senden und irgendwo wird vielleicht mal was empfangen, muss ins Chaos führen.
:
Bearbeitet durch User
Johann L. schrieb: >> PS: dabei kommt mir noch die Frage, wieviele Interrupts die AVR denn >> überhaupt schachteln können... > > Bis der Platz auf dem Stack aus ist; bzw. bis der Stack in den anders > genutzten Speicher bzw. Adressbereich hineinwächst: Heap, Static > Storage, I/O-Bereich, ... Lol. AVR kann keine Interrupts schachteln, d.h. es kann von jedem Interrupt nur einer gemerkt werden. Wenn während einer INT0-isr Timer_1 dreimal zuschlägt, wird die Timer_1-isr nach der INT0-isr trotzdem nur einmal ausgeführt. M328P z.B. hat 26 Int-Vectors, soviel Stack*2 wird im schlimmsten Fall ohne dein Zutun verbraucht. Wieviel Stack einzelne isr verbraucht ist uninteressant, da der benutzte Platz auf dem Stack nach der isr wieder freigegeben wird. Und was die "Ratschläge" mit wiedersetzen des Interrupts Flag betrifft: Interrupts in der isr wieder freigeben ist schlicht gesagt dumm - nix ist so wichtig, daß die paar us nicht gewartet werden kann. Was ist wenn in irgendeiner isr dieselbe isr wieder zuschlägt? Ist diese isr re-entrant, was ist wenn der benötigte Pointer nicht rechtzeitig erhöht wurde, wenn I/O Register nicht ausgelesen ist? Isr soll, wie schon jemand geschrieben hat, so kurz wie nur möglich sein, am besten nur mit Flag setzen, ev. ein Byte reinschreiben und alles andere soll dann eine State-Machine in main() erledigen.
Marc V. schrieb: > AVR kann keine Interrupts schachteln, d.h. es kann von jedem Interrupt > nur einer gemerkt werden. > Wenn während einer INT0-isr Timer_1 dreimal zuschlägt, wird die > Timer_1-isr nach der INT0-isr trotzdem nur einmal ausgeführt. > M328P z.B. hat 26 Int-Vectors, soviel Stack*2 wird im schlimmsten Fall > ohne dein Zutun verbraucht. Wieviel Stack einzelne isr verbraucht ist > uninteressant, da der benutzte Platz auf dem Stack nach der isr wieder > freigegeben wird. Liest du auch, was du schreibst? Defaultmässig ist beim AVR immer nur eine einzige ISR aktiv, die benötigt auf dem Stack den Platz für eine Rücksprungadresse plus das, was die ISR selber anlegt, unabhängig davon, wie viele Int-Vekoren der Prozessor hat. Setzt man das I-Flag in den ISRs, dann können beliebig viele ISRs geschachtelt werden, bzw. so viele, bis der Stack überläuft. Oliver
Rainer V. schrieb: > Sorry, aber ich versuche ein > Gefühl für Interrupts zu bekommen Gerade dann solltest Du Dir nicht gleich Schweinereien angewöhnen, sondern erstmal sicher und zuverlässig bleiben. Gerade Interrupts, die etwas mehr tun sollen, löschen nicht ihr Interruptflag automatisch beim Eintritt, d.h. legen Dir die Bananenschale aus. Wenn Du unbedingt drauf ausrutschen willst, nur zu.
Marc V. schrieb: > Johann L. schrieb: >>> PS: dabei kommt mir noch die Frage, wieviele Interrupts die AVR denn >>> überhaupt schachteln können... >> >> Bis der Platz auf dem Stack aus ist > Lol. > AVR kann keine Interrupts schachteln, > d.h. es kann von jedem Interrupt nur einer gemerkt werden. Das sind zwei verschiedene Paar Schuhe. Auch µC mit schachtelbaren Interrupts haben i.d.R. nur ein "interrupt pending" bit pro Interrupt- Quelle. Sie können sich genauso wie der AVR nur einen Interrupt pro Quelle merken. Wenn Interrupts lange genug gesperrt sind (warum auch immer) und die gleiche Quelle mehrfach auslöst, dann gehen alle Interrupts bis auf einen verloren. Ist halt so. > Wieviel Stack einzelne isr verbraucht ist > uninteressant, da der benutzte Platz auf dem Stack nach der isr > wieder freigegeben wird. Aber erst am Ende. Wenn eine ISR von einem (anderen) Interrupt unterbrochen wird, dann ist das genauso wie ein Funktionsaufruf. Es wird ein Stackframe erzeugt und die "neue" ISR aufgerufen. Je nach Schachtelungstiefe kann da durchauch einiges an Stackspace zusammen kommen. > Und was die "Ratschläge" mit wiedersetzen des Interrupts Flag betrifft: > Interrupts in der isr wieder freigeben ist schlicht gesagt dumm - nix > ist so wichtig, daß die paar us nicht gewartet werden kann. Aha. Komischerweise haben viele andere µC (so ziemlich alle außer den AVR) schachtelbare Interrupts, oft sogar mit manuell vergebbaren Prioritäten. Das haben die Hersteller bestimmt deswegen eingebaut, weil es niemand braucht. </ironie> > Was ist wenn in irgendeiner isr dieselbe isr wieder zuschlägt? Dann war der Programmierer dämlich. Bei einer Timer-ISR versteht es sich von selbst, daß die ISR nicht länger brauchen darf als ein Timer-Intervall. Und wenn man keine Kontrolle über das Zeitverhalten hat (z.B. Pin-Change Interrupt) dann muß man die Interrupt-Quelle (und nur die) innerhalb der ISR deaktivieren. µC mit schachtelbaren Interrupts machen das oft in Hardware. Erst wenn man das "interrupt pending" Bit manuell gelöscht hat, kann der gleiche Interrupt wieder zuschlagen. Also macht man das als letzte Aktion in der ISR und alles ist schick. Beim Z80 haben die Peripherie-Bausteine sogar auf dem Bus mitgelauscht, um die RETI Instruktion zu erkennen und erst danach wieder einen Interrupt auszulösen. > Isr soll, wie schon jemand geschrieben hat, so kurz wie nur möglich > sein, am besten nur mit Flag setzen, ev. ein Byte reinschreiben und > alles andere soll dann eine State-Machine in main() erledigen. Das ist die Methode für Dummies. Macht man nichts mit verkehrt, aber man macht sich sehr wahrscheinlich viel mehr Arbeit als nötig. Kann man so machen, muß man aber nicht. So lange das Zeitverhalten des Codes deterministisch ist, darf eine ISR auch 1000 Takte oder länger laufen. Und wenn es andere Interrupts gibt, die nicht so lange warten können, dann macht man die ISR eben unterbrechbar (AVR) bzw. priorisiert den anderen Interrupt höher. BTDTMT.
:
Bearbeitet durch User
Axel S. schrieb: > Aha. Komischerweise haben viele andere µC (so ziemlich alle außer den > AVR) schachtelbare Interrupts, oft sogar mit manuell vergebbaren > Prioritäten. Das haben die Hersteller bestimmt deswegen eingebaut, weil > es niemand braucht. </ironie> Ohne Prioritäten ist das Konzept halt wenig sinnvoll, und für einen vollwertigen Interrupt-Controller war auf den alten AVRs wohl nicht genügend Platz. Die neuen Modelle können da ja inzwischen auch mehr. Oliver
Danke für die vielen Anregungen! Mein momentaner Entwurf geht tatsächlich von einer Master-Slave Topologie aus. Der Master fragt einen Slave und zwar so lange, bis der geantwortet hat. Natürlich mit einem Timeout... Der Slave seinerseits hat daneben drei Prozesse, die er anstößt und von denen einer seine Daten über ein Pulslängenprotokoll zurückgibt. Wenn ich dieses Paket unterbreche, sind die Daten ungültig/falsch. Eine Anfrage vom Master soll die laufenden Prozesse nicht unterbrechen, sondern erst bedient werden, wenn der Slave quasi "Idle" ist. Das sollte also alles nicht in eine verschachtelte "Interruptorgie" ausarten. Wollte eben nur fragen, ob ich den Interruptmechanismus beim AVR richtig verstanden habe. In den nächsten Tagen bekomme ich RS-422-Bausteine, mit denen ich die Halb-Duplex-Verbindung aufbauen will. Dann sehe ich weiter! Gruß Rainer
Hallo, eines musst du nochmal erklären was du vorhast, ich denke du verrennst dich in der Interruptorgie. Wofür benötigst du eine Interruptverschachtelung für die Kommunikation? Du musst nur die USARTs und das Protokoll richtig programmieren. Dann schickt der Master eine Anfrage raus und wartet auf Antwort. Während er wartet kann er andere Dinge machen. Ohnen jeden zusätzlichen Interrupt. Die USART Daten liest du nebenbei mit ein, diese Hardwareeinheit hat selbst Interrupts, dass reicht aus.
:
Bearbeitet durch User
Axel S. schrieb: >> Isr soll, wie schon jemand geschrieben hat, so kurz wie nur möglich >> sein, am besten nur mit Flag setzen, ev. ein Byte reinschreiben und >> alles andere soll dann eine State-Machine in main() erledigen. > > Das ist die Methode für Dummies. Nein, es ist eher andersrum - zumindest beim AVR. Nur Dummies und LED-Blink "Programmer" versuchen, alles in der isr zu machen. > Macht man nichts mit verkehrt, aber man > macht sich sehr wahrscheinlich viel mehr Arbeit als nötig. Kann man so > machen, muß man aber nicht. Wieso man sich damit viel mehr Arbeit macht, ist mir unklar... Gerade deswegen findet man State-Machine in jedem ernstzunehmendem Programm, welches mit Interrupts zu tun hat. Und isr, welche von einer anderen isr unterbrochen werden dürfen, sind sowas von unwichtig bzw. Zeitunkritisch, die sind doch nur dafür da, um nicht in der main() ständig unwichtige Sachen abfragen zu müßen, z.B. LichtSensor, TempSensor, um auf Helligkeits- und Temperatur- veränderungen zu reagieren - (Displays etc.). Nichts, wo man einen AVR einsetzt, braucht isr die unterbrochen werden muß, vorausgesetzt, man macht es nicht wie die Dummies und versucht sturr, alles in der isr zu erledigen. Und selbst wenn - 16000 Takte dauern gerade mal 1ms. Für wirklich zeitkritische Aufgaben delegiert man die Arbeit ganz einfach, aber das ist schon eine andere Klasse - weit über AVR.
:
Bearbeitet durch User
Beitrag #6406585 wurde vom Autor gelöscht.
Beitrag #6406593 wurde von einem Moderator gelöscht.
Veit D. schrieb: > eines musst du nochmal erklären was du vorhast, ich denke du verrennst > dich in der Interruptorgie. Hi, ich habe mich nicht in eine Interrupt-Orgie verrannt, sondern lediglich nach Verständnis gefragt! Ob ich mein Problem so oder so löse, hängt von ein paar Dingen ab...auch von den Infos, die hier bekommen habe. Und klar, dass jetzt wieder die gelangweilten Besserwisser aufschlagen...eigentlich viel zu spät! Vermutlich haben sie erst jetzt mein Problem verstanden, um es nun ausgiebig mißzuverstehn :-) Gruß Rainer
Beitrag #6407182 wurde von einem Moderator gelöscht.
Rainer V. schrieb: > Hi, ich habe mich nicht in eine Interrupt-Orgie verrannt, .. Ja, nee, iss klar .... Dutzende von µC sollen miteinander kommunizieren, und du beauskunftest ISR Interne, welche haarklein im Datenblatt erklärt werden. Die Probleme liegen doch ganz woanders. Fängt schon mit der Wahl/Erfindung des geeigneten Protokolls/Topologie an. Danach kann man auch über Interrupts nachdenken. Interrupts möglichst kurz: Eine brauchbare Strategie. Schlicht, einfach nachvollziehbar. Automaten in ISR: Schön für Protokolle. z.B. I2C Wiedereintrittsfähige ISR: > Wer Funk kennt, > nimmt lieber Kabel. So ist es auch mit der "Interrupt Reentrance". Die konsequente Variante: https://de.wikipedia.org/wiki/Interrupt#Interrupt-Service-Routinen_als_Programmierprinzip -------- Für welches Protokoll hast du dich entschieden?
Arduino Fanboy D. schrieb: > und du beauskunftest > ISR Interne, welche haarklein im Datenblatt erklärt werden. Ich habe gefragt, weil ich die "haarkleinen" Erklärungen eben nicht verstanden habe und zudem noch widersprüchliche bzw. fehlende Infos zum Interruptverhalten gefunden habe. Die oberlehrerhaften Aufforderungen, doch endlich einmal nur die Datenblätter zu studieren, dürfen aber selbstverständlich in einem Fachforum nicht fehlen...wenn dann aber jemand seitenweise versucht zu erklären, was er in einem Datenblatt nicht verstanden hat, dann kommen von den einschlägigen Spezialisten auch wieder nur die üblichen Anfeindungen. Da hift eben nur ignorieren, was ich persönlich auch (fast) immer mache! Nochmals Dank an alle, die ihr Wissen geteilt haben! Leider sind meine Schnittstellenbauteile heute nicht in der Post gewesen, sodass ich noch das ganze WE für Theorie habe. Gruß Rainer
Hugo H. schrieb: > Beitrag "Re: AVR Interrupt-Verhalten" "D.h. 1 Ereignis kann 'auf Halde' liegen ohne dass es 'übersehen' wird" Aber immer nur das letzte Auftreten eines Ereignisses (das letzte Setzen eines bestimmten Interrupt-Bits) wird "abgearbeitet". Es wird weder gezählt noch in irgendeiner "Interrupt-Reihenfolge (zum jeweiligen Interrupt / -Bit) verarbeitet.
Einige Feinheiten: Das von Anfängern gerne in Interrupts gemachte CLI/SEI ist Quatsch. Die Interruptlogik sperrt Interrupts automatisch beim Sprung in die Vectortabelle. Ich kenne auch keine andere Architektur, wo sowas nötig wäre. CLI sperrt Interrupts sofort. SEI, RETI geben Interrupts erst nach dem nächsten Befehl frei. Das ist wichtig, z.B. für atomares SEI+SLEEP. Auch wird das Main immer noch ausgeführt, wenn man den AVR mit Interrupts zuballert.
Hugo H. schrieb: > Aber immer nur das letzte Auftreten eines Ereignisses (das letzte Setzen > eines bestimmten Interrupt-Bits) wird "abgearbeitet". Es wird weder > gezählt noch in irgendeiner "Interrupt-Reihenfolge (zum jeweiligen > Interrupt / -Bit) verarbeitet. Das bedeutet auch, dass keine Zeit / kein Zeitpunkt des Auftretens festgehalten wird (ein Timer z. B. läuft weiter) - das sollte man "verinnerlichen" (neben den ggf. auftretenden zeitlichen "Verschiebungen" durch den Prolog etc. einer Interrupt-Serviceroutine)
:
Bearbeitet durch User
Ok, du halst also Slaves, die 1) Daten per PWM o.a. in die Welt senden und "gleichzeitgig" 2) Daten (auf Anfrage) zu einem Master senden (sollen). ad 1) * Ist das Soft-PWM? Nutzt du PWM-fähige Timer / Ports? * Welcher Jitter ist tolerierbar? Jitter kann man z.B. deduzieren, indem man die Port-Ausgabe zu Anfang ISR macht, und erst danch werden die neuen Daten Berechnet, z.B. ebenfalls in der ISR falls das passt. ad 2) * Wird per Software-Protokoll (welches?) zum Master gesendet? * Was passiert, wenn ein Slave nicht antwortet? * Gibt es Handshake-leitungen?
Marc V. schrieb: > Nein, es ist eher andersrum - zumindest beim AVR. > Nur Dummies und LED-Blink "Programmer" versuchen, alles in der isr > zu machen. So ein Unsinn. Alles (oder zumindest das allermeiste) in ISRs abzuhandeln ist vielmehr oft der effizienteste Weg. Ereignisorientierte Programmierung mit sehr stark reduzierter Notwendigkeit für teueres Polling und teuere Verzweigungen, denn das passiert dabei teilweise (Verzweigungen in state machines) bzw. sogar vollständig (polling entfällt) in HARDWARE. Man muss nur richtig programmieren können und nicht nur Wichsvorlagen zusammenschustern... Allerdings gibt es natürlich auch oft Gegenindikationen. Die kann man sehr einfach erfassen. Immer dann, wenn man in einer ISR in die Versuchung kommt, auf irgendwas warten zu wollen (bzw. zu müssen), dann ist das Konzept einer rein ISR-basierten Struktur der Anwendung zumindest zu überdenken. Manchmal lohnt es, das trotzdem zu machen, oft aber auch nicht. Trifft man hingegen nicht auf diese Versuchung, ist die rein ISR-basierte Anwendung (und das ist auch theoretisch beweisbar!) das ultima ratio. Jedenfalls so lange überhaupt Interrupts benutzt werden. Manchmal ist auch der komplette Verzicht darauf die effizienteste Lösung. Man muss einfach nur wissen, was man tut. Du weißt das definitiv immer noch nicht (nach so vielen Jahren: schändlich, weil nix dazu gelernt)!
c-hater schrieb: > Man muss nur richtig programmieren können und nicht nur Wichsvorlagen > zusammenschustern... Nein - man muss sich VORHER gut überlegen, was man in Interrupts behandeln will. Auch in Assembler kann man (auf einem 8-Bit AVR) z. B. nicht 100.000 Interrupts pro Sekunde "behandeln". Weder mit "Wichsvorlagen" noch mit C-Hater-Programmen. Gehirn einschalten (vor der Programmierung) ist angesagt - unabhängig von der Umsetzung in irgendeiner Programmiersprache. Ja - ich weiß - kritische Teile in Assembler (mein Prof. lallte immer auch von "Assembler-Unterprogrammen ..." :-)). Bisher kam ich (für meine Zwecke) meist ohne aus ...
:
Bearbeitet durch User
c-hater schrieb: > Marc V. schrieb: > >> Nein, es ist eher andersrum - zumindest beim AVR. >> Nur Dummies und LED-Blink "Programmer" versuchen, alles in der isr >> zu machen. > > So ein Unsinn. Alles (oder zumindest das allermeiste) in ISRs > abzuhandeln ist vielmehr oft der effizienteste Weg. Ungern, wirklich ungerne, gebe ich dir recht. Alleine schon wegen dem Prinzip, und weil du öfter mal unanständig agierst. Aber in diesem Fall muss ich sagen: Du hast Wahr! In Sachen ISR, kann man ganz entspannt auf jeglichen Dogmatismus verzichten, und sich stattdessen besser nach der Decke strecken. Also an den Notwendigkeiten orientieren. -- > Nur Dummies und LED-Blink "Programmer" versuchen, alles in der isr > zu machen Ein Seitenhieb auf Arduino? Dann daneben getroffen, denn Wire, Serial usw. bestehen, u.A. aus in der ISR implementierten Automaten. Es ist also auch dort Tradition, die ISR nicht unnötig zu verschlanken. Und das mit Fug und Recht.
Hugo H. schrieb: > Nein - man muss sich VORHER gut überlegen, was man in Interrupts > behandeln will. Natürlich. > Auch in Assembler kann man (auf einem 8-Bit AVR) z. B. > nicht 100.000 Interrupts pro Sekunde "behandeln". Doch, das kann man. Bei 20MHz Systemtakt bedeutet das einfach nur, dass die ISR insgesamt nicht länger als 198 Takte dauern darf (wenn main einfach nur eine Endlosschleife ist mit worst case: rjmp Anfang). Der minimale Interrupt-Overhead sind 8 Takte, bleiben also 190 nutzbare Takte. Ein gelernter Assemblerprogrammierer kann in 190 Takten eine Menge Zeug tun... Du nicht!
Arduino Fanboy D. schrieb: > Ungern, wirklich ungerne, gebe ich dir recht. > Alleine schon wegen dem Prinzip, und weil du öfter mal unanständig > agierst. > > Aber in diesem Fall muss ich sagen: Du hast Wahr! > > In Sachen ISR, kann man ganz entspannt auf jeglichen Dogmatismus > verzichten, und sich stattdessen besser nach der Decke strecken. Also an > den Notwendigkeiten orientieren. Lese ich das richtig? Du argumentierst für "umfangreiche Aktionen" in der ISR? Flags setzen ja - aber ganze "Aktionen"? Da muss ich meine Meinung über Dich wohl revidieren.
c-hater schrieb: > Du nicht! Die Regel sind max. 16 MHz - und es gibt Prolog und Epilog - aber Du bist ja der Über-Flieger und kannst alles. Chapeau. Mir doch egal :-) Was macht denn die "MAIN" wenn nur ISR prozessiert werden? Irgendwo beißt Du Dich in den Hintern :-)
:
Bearbeitet durch User
Hugo H. schrieb: > Du argumentierst für "umfangreiche Aktionen" in > der ISR? Ich sage: > An den Notwendigkeiten orientieren! Auch verstehe ich das Bestreben die ISR schlank zu halten. (aber nicht um jeden Preis) Hugo H. schrieb: > Da muss ich meine > Meinung über Dich wohl revidieren. Wenn du mich bisher als Dogmat eingestuft hast, dann kann ich dich nur bitten dieses zu revidieren.
Arduino Fanboy D. schrieb: > Wenn du mich bisher als Dogmat eingestuft hast Habe ich nicht - aber trotzdem ... :-(
Hugo H. schrieb: > Was macht denn die "MAIN" wenn nur ISR prozessiert werden? z.B. nut alles initialisieren und dann in der Schleife dauernd in den Schlafmodus schalten, sonst nix...
c-hater schrieb: > Der > minimale Interrupt-Overhead sind 8 Takte, bleiben also 190 nutzbare > Takte. Ein gelernter Assemblerprogrammierer kann in 190 Takten eine > Menge Zeug tun... Ja - Du "Super-Assembler-Programmierer" schaffts alles in einer ISR. Prolog und Epilog kannst Du vergessen (Du hast ja alles im Griff) und die restlichen Takte reichen immer. Für wie doof hälst Du eigentlich alle hier? Ich mag Deine Beiträge aber manchmal schwillt mir der Kamm.
Hugo H. schrieb: > Hugo H. schrieb: >> Beitrag "Re: AVR Interrupt-Verhalten" > > "D.h. 1 Ereignis kann 'auf Halde' liegen ohne dass es 'übersehen' wird" > > Aber immer nur das letzte Auftreten eines Ereignisses (das letzte Setzen > eines bestimmten Interrupt-Bits) wird "abgearbeitet". Eigentlich das erste. Ab da ist es ja gesetzt. Durch weitere Auftreten des Interrupts ändert sich am Flag nichts mehr. Wobei das eher eine philosophische Frage ist, ob es nu n der erste oder letzte ist. Der Interrupt wird halt als "aufgetreten" markiert, und da es nur einen Marker (das Flag) gibt, gibt es nur die Info darüber, dass er aufgetreten ist, aber nicht wie oft.
Hugo H. schrieb: > Die Regel sind max. 16 MHz Nicht in meiner AVR8-Welt. Die reicht offensichtlich weiter als deine... > und es gibt Prolog und Epilog Nö, in Assembler gibt es einen minimalen Interruptframe und der dauert bei den meisten AVR8 genau 8 Takte. Nur die ganz grossen mit 22-Bit PC und/oder die mit externem RAM brauchen ein paar Takte mehr. Das ist aber keine Geheimwissenschaft oder Raketentechnik, sonder steht schlicht im jeweiligen Datenblatt. Man muß es nur lesen... Das, was du als "Prolog/Epilog" bezeichnest, ist überwiegend unnützer C-Bullshit. In Assembler lacht man darüber... > aber Du > bist ja der Über-Flieger und kannst alles. Alles sicher nicht. Aber die AVR8 beherrsche ich doch noch 15 Jahren aktiver Entwicklungsarbeit wirklich nahezu perfekt. Bei den neueren klemmt's gelegentlich, da muss ich einfach auch noch das tun, was manche Leute nie tun: Lernen. > Was macht denn die "MAIN" wenn nur ISR prozessiert werden? I.d.R. nur eins: die MCU schlafen schicken. Genau genommen ist die Tatsache, dass in main nix weiter zu tun bleibt, das sichere Zeichen, dass man die optimale Lösung für die Anwendung gefunden hat...
Also, ich habe momentan 5 Slaves, die ich per RS422 anspreche und Daten haben möchte. Und wie schon geschrieben, haben die Slaves 3 Tasks, von denen ich eine nicht unterbrechen kann...ob das so sein/bleiben muß, lass ich mir noch mal durch den Kopf gehen. Ich habe jetzt (hoffentlich) verstanden, dass ich die Anfrage vom Master verliere, wenn der Slave in seiner "kritischen" Task werkelt oder ich lasse den Interrupt zu und zerstöre diese Task. Ohne jetzt nachgerechnet zu haben, denke ich, dass selbst die kürzeste Interrupt-Routine zu lang sein wird. Jetzt kann ich natürlich auch die Strategie des Master überdenken. Wie lange wartet der Master auf eine Antwort, fragt er nach diesem Timeout denselben Slave noch mal oder geht er zum nächsten oder ? Auch das Gesamttiming muß ich wohl noch mal für mich präzisieren. Gehe momentan davon aus, dass der Master etwa alle Sekunde neue Daten von allen Slaves haben muß. Das hört sich wie ewig an, bei Taktfrequenzen im MHz-Bereich, kann aber bei so einem System schon kurz genug sein. Ich arbeite übrigens entweder in Assembler oder in Forth und für mich gibt es die Regel, dass eine Interrupt-Routine so kurz wie möglich zu sein hat, schlicht nicht! Das hängt einfach "davon" ab... Gruß Rainer
Rainer V. schrieb: > Also, ich habe momentan 5 Slaves, die ich per RS422 anspreche und Daten > haben möchte. Und wie schon geschrieben, haben die Slaves 3 Tasks, von > denen ich eine nicht unterbrechen kann... Warum kannst du diesen Task nicht unterbrechen? Das gibt es normalerweise nicht. Finde heraus, wie lange du ihn unterbrechen könntest, ohne seine Funktion zu gefährden!
c-hater schrieb: > Das, was du als "Prolog/Epilog" bezeichnest, ist überwiegend unnützer > C-Bullshit. In Assembler lacht man darüber... Falls du dich auf avr-gcc beziehst, das ist schon seit bereits 3 Compiler-Versionen nicht mehr so. Soviel zu "Lernen".
c-hater schrieb: > Nö, in Assembler gibt es einen minimalen Interruptframe und der dauert > bei den meisten AVR8 genau 8 Takte. Wie das? Wenn ein Interrupt eintritt, passiert folgendes: - die aktuelle Instruktion wird fertig ausgeführt (0 bis 4 Takte) - Sprung in die Interrupt-Vektor-Tabelle (4 Takte) - üblicherweise RJMP zur ISR (2 Takte) <Inhalt der ISR> - RETI (4 Takte) Macht zusammen 10 bis 14 für eine leere ISR und nicht "genau 8". Wenn man dann noch das SREG und wenigstens ein Register sichern will, damit die ISR auch was tun kann, kommen gleich nochmal 10 dazu. (PUSH R16, IN R16, SREG, PUSH R16 und am Ende das umgekehrte). Also sprich, so 20 bis 24 und pro weiterem zu sicherndem Register nochmal 4, und dann kann man mal mit dem eigentlichen Inhalt der ISR anfangen.
Die Moral von der Gschicht' Anstatt immer über den Zaun zu gucken, muß man eben mit den Fähigkeiten und Beschränkungen der jeweiligen uC zurechtkommen und optimal innerhalb dieser Grenzen operieren. Nur weil es vielleicht irgendwo etwas Besseres möglicherweise gibt, bedeutet das noch lange nicht, daß einfachere Architekturen nicht doch nützlich sind. Bis jetzt konnte ich meine Anwendungen auf jeden uC zum ordnungsgemäßen Laufen bekommen. Ich kann leider nicht nachvollzuziehen warum darüber so viel Gedöhns gemacht wird. Firmen wie R&S konstruierten in den 80er Jahren beeindruckende Meßgeräte mit heutzutage vergleichbar sehr beschränkter uC Technik. Sie wußten eben das Beste aus der zur zur Verfügung stehenden Ressource herauszukitzeln und hatten fundierte Programmierkenntnisse. Man hatte auch nicht so viele Flausen im Kopf und beschränkte sich auf die wirklich notwendige Funktionalität. Heutzutage ergeht man sich im Konsumerbereich in aus der Hand gehende Featureorgien und Spyware ist das Holy Grail der Entwickler und Marketiergurus. OK. AVR hat gewisse Defizite. Das heißt aber noch lange nicht, der AVR wäre nutzlos nur weil gewisse Beschränkungen in engen Bereichen bei anderen Architekturen besser gelöst ist. Nicht jeder Entwickler stößt gegen solche Grenzen.
Johann L. schrieb: > Falls du dich auf avr-gcc beziehst, das ist schon seit bereits 3 > Compiler-Versionen nicht mehr so. Soviel zu "Lernen". Ah ja. Deann setze enfach eines der beiden von mir veröffentlichen Anwendungen (zu finden in Projekte & Code) in C um, meinetwegen auch im topaktuellen avr-gcc. Es wird dir nicht gelingen. Erst, falls das doch der Fall wäre, gäbe es für mich etwas zu lernen... Wird aber nicht passieren. Dazu müßte der Compiler weit über Funktionsebene optimieren können und eine Vorstellung über den Impact einer ISR in der Gesamtanwendung haben. Kann er aber nicht... Du machst immer wieder denselben Fehler (wie einige andere auch): Du glaubst, weil ich es ablehne, diesen Scheiß freiwillig zu benutzen, hätte ich keine Ahnung davon... Und: Du kannst NIX, was der Compiler nicht kann, jedenfalls nicht, ohne auf Asm zurückzugreifen. Also selbst wenn du mit solchen unfairen Tricks zu einer Lösung kommen solltest (was immerhin Kompetenz beweisen würde), würde das Ergebnis genauso "portabel" sein wie mein nativer Assemblercode. Also wäre die Verwendung von C und der ganze Sackstand damit absolut nutzlose Wichse... Aber das können wir dann diskutieren, wenn du die C-Lösung fertig hast...
c-hater schrieb: > Johann L. schrieb: > >> Falls du dich auf avr-gcc beziehst, das ist schon seit bereits 3 >> Compiler-Versionen nicht mehr so. Soviel zu "Lernen". > > Ah ja. Deann setze enfach eines der beiden von mir veröffentlichen > Anwendungen (zu finden in Projekte & Code) in C um, meinetwegen auch im > topaktuellen avr-gcc. Es wird dir nicht gelingen. > > Erst, falls das doch der Fall wäre, gäbe es für mich etwas zu lernen... Du hättest ja schon was gelernt, wenn du nicht immer wieder veraltete Sachstände repetieren würdest. > Und: Du kannst NIX, was der Compiler nicht kann, Stimmt. Es gibt aber Dinge, die der Compiler wesentlich schneller kann als ich, und wenn es nicht Resource-kritisch ist, hab ich mit ein paar % Overhead kein Problem.
:
Bearbeitet durch User
c-hater schrieb: > Warum kannst du diesen Task nicht unterbrechen? Das gibt es > normalerweise nicht. Ja, normalerweise...und ich meine, ich hätte schon geschrieben, dass es sich um ein "uraltes" Modul aus der Bastelkiste handelt, dass ich jetzt einfach mal benutzen will. Es taktet seine Daten in einem festen Frame von ca. 20ms alle Sekunde raus. Es kann nicht angestossen werden - ansonsten wäre das Problem natürlich vom Tisch. Und um es gleich zu sagen, diese Task läuft natürlich schon in einer Interrupt-Routine. Selbst wenn ich die Zeit, in der alle Slaves ihre Daten übermittelt haben müssen, auf 2s lege, muß ich doch quasi 6 asynchrone Ereignisse, die sich alle irgendwie blockieren können, in dieser Zeit "geschafft" haben. Muß mangels Hardware jetzt noch mal genauer in das Timing des Systems/Programms einsteigen. Danke und gute Nacht, Rainer
Rolf M. schrieb: > Wie das? Wenn ein Interrupt eintritt, passiert folgendes: > > - die aktuelle Instruktion wird fertig ausgeführt (0 bis 4 Takte) Das ist eine Sache, die einzig für die Latenz relevant ist, nicht aber für den Durchsatz. Wenn du nicht einmal das (oder auch nur den Unterschied) begriffen hast, tust du mir leid... Die Sache ist einfach die: egal an welchem Punkt unterbrochen wurde, die von main sozusagen geklaute Zeit wird am Ende der ISR in main auch weniger gebraucht... > - Sprung in die Interrupt-Vektor-Tabelle (4 Takte) Genau genommen ist das die erste Hälfte des unumgänglichen Interruptframe. Allerdings stellst du das vollkommen falsch dar. Es gibt keinen "Sprung in die Interrupt-Vektor-Tabelle". Das passiert in Hardware ohne Taktkosten (wird nebenbei erledigt). Was kostet, ist das Ablegen der Rücksprungadresse der ISR auf dem Stack. Deswegen (und nur deswegen) variiert der Minimum-Frame. Bei 22Bit-PC müssen halt nicht nur zwei, sondern drei Bytes Returnadresse auf den Stack gelegt werden und bei externem RAM kosten ein Bytezugriff auf das SRAM halt (mindestens) drei und nicht nur zwei Takte. > - üblicherweise RJMP zur ISR (2 Takte) Das kann man in Assembler ggf. umgehen. In-place-ISR. Der Code der ISR fängt einfach direkt auf dem Vektor an. > - RETI (4 Takte) Da passiert die zweite Hälfte des unvermeidlichen Minimalframe. Aber das ist spiegelbildlich zu dem, was beim Interupteintritt passiert. Bestimmend ist der Aufwand, die Rücksprungadresse vom Stack zu holen. Im Minumum bleibt für den Durchsatz halt 4 Takte für den Eintritt in die ISR und 4 Takte für den Return.
Rainer V. schrieb: > Es taktet seine Daten in einem festen Frame von ca. 20ms > alle Sekunde raus. 20ms sind doch ewig; in der Zeit sind schon Weltreicht aufgestiegen und wieder zerfallen... 20ms sind 20000 Ticks/MHz, bei 16MHz zum Beispiel 320000 Ticks. Ist Fortran oder dein OS / Task-System so ineffizient? Oder entsprechen die 20ms der Frequenz, d.h. alle 20ms wird ein Puls der PWM ausgegeben? Momentan ist immer noch unklar, wie die Nachrichtenformate genau aussehen, und welche Jitter etc. sie akzeptieren.
Johann L. schrieb: > Stimmt. Es gibt aber Dinge, die der Compiler wesentlich schneller kann > als ich, und wenn es nicht Resource-kritisch ist, hab ich mit ein paar % > Overhead kein Problem. Sprich: De facto gibst du also zu, dass ich in Assembler effizienteren Code produzieren kann als dein topaktueller Compiler. Nur um das mal (auch für die Dummies vollkommen zweifelsfrei) klarzustellen...
c-hater schrieb: > Johann L. schrieb: > >> Stimmt. Es gibt aber Dinge, die der Compiler wesentlich schneller kann >> als ich, und wenn es nicht Resource-kritisch ist, hab ich mit ein paar % >> Overhead kein Problem. > > Sprich: De facto gibst du also zu, dass ich in Assembler effizienteren > Code produzieren kann als dein topaktueller Compiler. Nur um das mal > (auch für die Dummies vollkommen zweifelsfrei) klarzustellen... Das ist keine Kunst, das kann ich auch. Aber in 99% der Fälle brauch ich's eben nicht. Ich genieße dann dass der Code in einem Augenblick übersetzt ist, und ich mich nicht mit Registerallokierung, Runterbrechen von Arithmetik, Jumpty-Jumps etc. rumplagen muss. Aber wenn man Zeit genug hat und ein ästethisches Bedürfnis danach hat, den endeffizienten Code zu klöppeln — bitteschön. Aber lass uns nicht schon *wieder* in irgendwelche fruchtlosen, überflüssige Rants verfallen. Zu dem Thema wurde wirklich schon alles geschrieben.
Johann L. schrieb: > Das ist keine Kunst, das kann ich auch. Beweise es. Behaupten kann man viel... > Aber in 99% der Fälle brauch > ich's eben nicht. Natürlich. Das ist völlig unstrittig. Brauchen tut man diese Kompetenz nur, wenn man aus gegebener Hardware das Maxium an Performance herausholen muss. Das ist relativ selten. Hardware ist heute zu billig geworden. Nimmt man halt einen potenteren Controller... Aber: Wenn man in einer bestehenden Lösung noch ein bissel Funktionalität einbauen muss, obwohl diese bereits ausgereizt war, dann kann diese Kompetenz sehr nützlich sein. Und sich direkt massiv in (bei der Hardware gesparten) Euro auszahlen... > Ich genieße dann dass der Code in einem Augenblick > übersetzt ist, und ich mich nicht mit Registerallokierung, Runterbrechen > von Arithmetik, Jumpty-Jumps etc. rumplagen muss. Aber wenn man Zeit > genug hat und ein ästethisches Bedürfnis danach hat, den endeffizienten > Code zu klöppeln — bitteschön. Reiner Softwerker, alles klar...
Rainer V. schrieb: > [...] > Muß mangels Hardware jetzt noch mal genauer in das Timing des > Systems/Programms einsteigen. > Danke und gute Nacht, Rainer Ich halte es für denkbar, dass Dir dabei noch folgendes Detail von Nutzen sein könnte: Die Interrupts haben eine "Priorität". Das bedeutet, dass, falls zu einem Zeitpunkt gleichzeitig zwei verschiedene, aktivierte Interrupts anhängig sind (pending), dann wird zuerst die ISR ausgeführt, welche in der Interrupt-Tabelle die niedrigere Adresse, und damit die höhere Priorität, hat. Siehe z.B. das Datenblatt vom ATMega169 oder den ATTiny24A usw. und dort im Kapitel "Reset and Interrupt Handling". Die Kapitelnummer kann je nach Typ variieren. Soweit mir bekannt gilt das Gesagte für alle AVRs. : gruss viel erfolg ;
c-hater schrieb: > Rolf M. schrieb: > >> Wie das? Wenn ein Interrupt eintritt, passiert folgendes: >> >> - die aktuelle Instruktion wird fertig ausgeführt (0 bis 4 Takte) > > Das ist eine Sache, die einzig für die Latenz relevant ist, nicht aber > für den Durchsatz. Natürlich ist die relevant. Denn wie du ja selbst schreibst, wird nach einem RETI oder CLI immer erst noch eine Instruktion ausgeführt, bevor der nächste Interrupt kommt. Du kannst also niemals die ISR zweimal direkt hintereinander ausführen, ohne dass du dazwischen auf die Abarbeitung einer Instruktion warten musst. > Die Sache ist einfach die: egal an welchem Punkt unterbrochen wurde, die > von main sozusagen geklaute Zeit wird am Ende der ISR in main auch > weniger gebraucht... Hast du nicht von einem Programm gesprochen, das alles in der ISR macht und dessen Hauptschleife nur aus einem RJMP zu sich selbst besteht? Dann hast du immer die zwei Takte an zusätzlicher Laufzeit zwischen zwei Ausführungen der ISR. Die hast du doch oben sogar selbst mit berücksichtigt. >> - Sprung in die Interrupt-Vektor-Tabelle (4 Takte) > > Genau genommen ist das die erste Hälfte des unumgänglichen > Interruptframe. Allerdings stellst du das vollkommen falsch dar. Es gibt > keinen "Sprung in die Interrupt-Vektor-Tabelle". Das passiert in > Hardware ohne Taktkosten (wird nebenbei erledigt). Was kostet, ist das > Ablegen der Rücksprungadresse der ISR auf dem Stack. Das ist für mich Teil des Sprungs in die Interrupt-Vektor-Tabelle, ähnlich wie bei einem CALL. >> - üblicherweise RJMP zur ISR (2 Takte) > > Das kann man in Assembler ggf. umgehen. In-place-ISR. Der Code der ISR > fängt einfach direkt auf dem Vektor an. Das ist dann aber auch wieder so ein Spezialfall. Das ist halt der Unterschied. Du siehst es als Normal an, jede Menge Sonderfälle auszunuten, um noch einen oder zwei Taktzyklen zu sparen. Für mich ist der Normalfall erstmal einer, der sauber und ohne fiese Tricks auskommt und in der Regel immer so nutzbar ist. Nur, wenn mir der nicht ausreicht (was eher selten vorkommt), schaue ich, ob ich derartige Abkürzungen, die ja meistens auf die Übersichtlichkeit des Code einen negativen Einfluss haben, nehmen kann.
Beitrag #6409236 wurde vom Autor gelöscht.
c-hater schrieb: > Bei 22Bit-PC müssen halt nicht nur > zwei, sondern drei Bytes Returnadresse auf den Stack gelegt werden nee so einfach ist das nicht! https://en.wikipedia.org/wiki/Atmel_AVR_instruction_set es gib den mega 2560 der hat tatsächlich 3 Adressbytes für den RTI (Rare) models with >128 KiB of ROM have a 3-byte program counter. Subroutine calls and returns use an additional byte of stack space, there is a new EIND register to provide additional high bits for indirect jumps and calls, and there are new extended instructions EIJMP and EICALL which use EIND:Z aber der mega 1284p hat ja definitiv NICHT >128 KiB of ROM und somit wieder seine Ausnahmeregel: Models with >64 KiB of ROM add the ELPM instruction and corresponding RAMPZ register. LPM instructions zero-extend the ROM address in Z; ELPM instructions prepend the RAMPZ register for high bits. This is not the same thing as the more general LPM instruction; there exist "classic" models with only the zero-operand form of ELPM (ATmega103 and at43usb320). When auto-increment is available (most models), it updates the entire 24-bit address including RAMPZ. (Rare) models with >64 KiB of RAM address space extend the 16-bit RAM addressing limits with RAMPX, RAMPY, RAMPZ and RAMPD registers. These provide additional high bits for addressing modes which use the X, Y, or Z register pairs, respectively, or the direct addressing instructions LDS/STS. Unlike ROM access, there are no distinct "extended" instructions; instead the RAMP registers are used unconditionally. und damit war mein Timing bei m1284p 10% langsamer als beim 328p und nicht durch ein vermutetes und nicht vorhandenes drittes Adressbyte!
:
Bearbeitet durch User
Rolf M. schrieb: > Natürlich ist die relevant. Denn wie du ja selbst schreibst, wird nach > einem RETI oder CLI immer erst noch eine Instruktion ausgeführt, bevor > der nächste Interrupt kommt. Jepp. Genau deswegen ergab in meiner Rechnung ja auch 20.000.000/100.000 nicht 200, sondern nur 198 Takte... > Das ist für mich Teil des Sprungs in die Interrupt-Vektor-Tabelle, > ähnlich wie bei einem CALL. Du hast eben keine Ahnung von dem, was die Hardware tatsächlich tut... > Das ist dann aber auch wieder so ein Spezialfall. Das ist halt der > Unterschied. Du siehst es als Normal an, jede Menge Sonderfälle > auszunuten, um noch einen oder zwei Taktzyklen zu sparen. Wenn ich eine ISR habe, die alle 200 Takte aufgerufen wird, dann spare ich durch diese zwei Takte weniger in der ISR schonmal ein 1% Rechenzeit ein, ohne an möglicher Funktionalit der ISR zu verlieren. Wird die ISR hingegen alle 20 Takte ausgeführt, spare ich schon 10% Rechenzeit durch diesen Trick ein. Begreifst du die Konsequenz? Man muss einerseits abwägen, ob es sinnvoll ist. Und andererseits überhaupt die Möglichkeit haben, notfalls auf dieses Mittel zurückzugreifen. In Assembler habe ich sie. Ohne große Verrenkungen... > Für mich ist > der Normalfall erstmal einer, der sauber und ohne fiese Tricks auskommt Fies sind solche Tricks nur für den, der sie nicht versteht. Das ist der Punkt. Die Hardware sagt was geht. Und es ist Aufgabe des Programmierers, sie bestmöglich zu nutzen. Macht übrigens auch jeder C-Compiler nicht anders. Im Rahmen der Fähigkeiten der Verfasser des Codegenerators für das jeweilige Zielsystem. Und was konkret den avr-gcc angeht, besteht da immer noch viel Potential für Verbesserungen. Diese sind allerdings de facto oft wegen der Sprache selber nicht möglich. Die hat Axiome, um die der Codegenerator herumlavieren muss. C weiss nix von Interrupts, C weiß nix von mehreren Adressbereichen, C weiß eigentlich praktisch garnix von der Realität. Aber das ist ja kaum noch relevant, die Unterstützung für AVR8 ist ja eh' quasi abgekündigt. Man könnte sich also zurücklehnen. Aber nö: Bei ARM z.B. könnte man die Sachlage genau wie oben für den AVR8 zusammenfassen und mit "neuen" Hardware-Schmankerln anreichern, von denen C auch wieder rein garnix weiß. Angefangen von DMA, weiter über per ExtMem eingebundenen Speicher usw. usf. Ja, irgendwie alles notdürftig über C benutzbar gemacht, aber weit weg davon, optimal zu sein. Richtig beherrschen kann all den Scheiß nur ein Assemblerprogrammierer. Und der hat ordentlich zu tun damit.
c-hater schrieb: > Jepp. Genau deswegen ergab in meiner Rechnung ja auch 20.000.000/100.000 > nicht 200, sondern nur 198 Takte... sicher? auch bei 328p 1284p und 2560? immer 198 Takte? glaube ich nun nicht!
Joachim B. schrieb: > und damit war mein Timing bei m1284p 10% langsamer als beim 328p > und nicht durch ein vermutetes und nicht vorhandenes drittes Adressbyte! 1) Ich würde niemals vermuten, dass der 1284P einen 22Bit-PC hat. Ich habe schließlich das Datenblatt gelesen... 2) Dein Timing war nicht Assemblercode sondern C, richtig? Dann weißt du, dass du nix weißt, sondern dich auf den Compiler verläßt. Dabei sollte jeder wissen, dass C KEINERLEI Timing garantiert... Der Minumum-Interruptframe beträgt beim 1284P 8 Takte. Wie bei den meisten AVR8. Wenn dein C-Compiler mehr braucht, ist dein C-Compiler Scheiße oder du. So einfach ist das. Vermutlich hättest du nicht aus der ISR auf konstante Daten im Flash (oberhalb 64k) zugreifen sollen, dann hätte es der Compiler sich geklemmt, RAMPZ zusätzlich auf den Stack zu legen. So gut isser ja nun inzwischen schon (wenn auch noch nicht seit so furchtbar langer Zeit, eigentlich erst, seitdem er überhaupt mit Flash >128k umgehen kann)...
Joachim B. schrieb: > auch bei 328p 1284p und 2560? > immer 198 Takte? > > glaube ich nun nicht! Ich auch nicht. Denn der 2560 hat natürlich notwendigerweise einen 22Bit-PC.
1. Was, glaub ich, noch nicht explizit gesagt wurde: Das Interruptflag der jeweiligen Interruptquelle wird beim Aufruf der ISR gelöscht. D.h. der gleiche Interrupt kann während der Abarbeitung schon "anstehen". 2. Man könnte sich selbst eine Priorisierung basteln, indem man in der ISR die Interruptflags ausliest und ggf. die zugehörigen ISRs auslöst und das Flag dann per Software löscht.
Joachim B. schrieb: > immer 198 Takte? > glaube ich nun nicht! c-hater schrieb: > Ich auch nicht. Denn der 2560 hat natürlich notwendigerweise einen > 22Bit-PC. und der 1284p nicht mal diesen, also war dein c-hater schrieb: > Jepp. Genau deswegen ergab in meiner Rechnung ja auch 20.000.000/100.000 > nicht 200, sondern nur 198 Takte... falsch weil unpräzise? Deine Rechnung mag richtig sein, ohne Nennung von CPU/MCU wertlos! Es gibt ja mehr als AVR und dort mehr als den 328p.
:
Bearbeitet durch User
>2. Man könnte sich selbst eine Priorisierung basteln, indem man in der >ISR die Interruptflags ausliest und ggf. die zugehörigen ISRs auslöst >und das Flag dann per Software löscht. Ja, kann man machen. Vielleicht sollte man aber etwas anderes machen, wenn der Quotient aus der CPU-Leistung und den Anforderungen der Applikation dermaßen nahe an 1 liegt, dass man sich um das Einsparen einer Handvoll Takte Gedanken machen muss, nämlich sich überlegen, ob dann nicht die Wahl eines Prozessors mit mehr Rumms vielleicht die bessere Lösung wäre. Just my two cents.
Ich würds auch nicht machen, aber ist eben nicht so, dass keine rudimentäre Priorisierung möglich wäre. Oft ist es ja so, man denkt, man müsste es auf eine bestimmte Art machen (die der µC vielleicht gar nicht bietet) und merkt erst im Lauf der Implementierung, dass das garnicht so kritisch ist.
So, nachdem wir nun gesehen haben, dass man von 200 CPU-Zyklen 2! einsparen kann (natürlich nur, wenn man schlau ist...), kommen nun die Vorschläge, eine "dickere" Maschine zu benutzen. Allerdings ohne auf mein Problem einzugehen. Ich antworte jetzt ohne Zitate auf die für mich relevanten Beiträge! 1. Ja, es ist mir klar, dass die INterrupts eine Priorität haben. Und nach neuerlichem Studium der Docs stellt sich mir wieder die Frage, ob z.B. das Interrupt-Bit - etwa von Timer - auch gesetzt wird, wenn der globale Interrupt nicht gesetzt ist. Wenn der globale Interrupt gesetzt ist, dann wird doch wohl die entsprechende Routine angesprungen...wenn nicht, dann wird die Routine eben nicht aufgerufen, ich wüßte aber zumindest, das da ein Interrupt war oder??!! 2. Wenn also mehrere Interrupts auflaufen, werden diese dann gemäß ihrer Priorität ausgeführt. Jeweils direkt nach dem RETI des vorhergehenden? 3. Natürlich sind 20ms nicht viel. Ich habe hier aber ein System von 10 Prozessen auf 6 Controllern, die völlig asynchron ablaufen. Und ich will da eine Datenkonsistens von min. 2s realisieren. Und dieses Problem besteht doch völlig unabhängig von den eingesetzten Komponenten. Selbst wenn ich da 6 PC's zusammenklöppeln würde, wäre ich keinen Schritt weiter. Gruß Rainer, und bei diesem herrlichen Spätsommerwetter verabschiede ich mich nun in Garten und an Grill :-)
Rainer V. schrieb: > stellt sich mir wieder die Frage, ob > z.B. das Interrupt-Bit - etwa von Timer - auch gesetzt wird, wenn der > globale Interrupt nicht gesetzt ist AVR? Dann auf jeden Fall: Ja! Rainer V. schrieb: > 2. Wenn also mehrere Interrupts auflaufen, werden diese dann gemäß ihrer > Priorität ausgeführt. Jeweils direkt nach dem RETI des vorhergehenden? AVR? Es wird immer der Interrupt mit der höchsten Priorität ausgeführt. Rainer V. schrieb: > 3. Das ist völlig unverständlich für mich.
Rainer V. schrieb: > 1. Ja, es ist mir klar, dass die INterrupts eine Priorität haben. Und > nach neuerlichem Studium der Docs stellt sich mir wieder die Frage, ob > z.B. das Interrupt-Bit - etwa von Timer - auch gesetzt wird, wenn der > globale Interrupt nicht gesetzt ist. Eigentlich steht das eindeuting da drin, aber halt in angelsächsisch. Ja, die einzelnen Interruptflags werden unabhängig vom globalen i-Flag gesetzt. Rainer V. schrieb: > 2. Wenn also mehrere Interrupts auflaufen, werden diese dann gemäß ihrer > Priorität ausgeführt. Jeweils direkt nach dem RETI des vorhergehenden? Wie weiter oben schon mehrfach geschrieben wurde, wird nach einem Reti ein Befehl des unterbrochenen Programms ausgeführt, ehe der nächste Sprung in eine ISR stattfindet. Oliver
Oliver S. schrieb: > Wie weiter oben schon mehrfach geschrieben wurde, wird nach einem Reti > ein Befehl des unterbrochenen Programms ausgeführt, ehe der nächste > Sprung in eine ISR stattfindet. Ok, habe ich so nicht registriert, ist aber wichtig! Auch wenn das unterbrochene Programm eine Interruptroutine war??? Arduino Fanboy D. schrieb: > Das ist völlig unverständlich für mich. Ist mir klar, weil du offensichtlich nur das liest, was du lesen möchtest. Trotzdem lese ich auch deine Beiträge wie jeden anderen...:-) Für mich bleibt es spannend! Gruß Rainer
Rainer V. schrieb: > Ok, habe ich so nicht registriert, ist aber wichtig! Auch wenn das > unterbrochene Programm eine Interruptroutine war??? Eine Interrupt-Routine ist für den AVR kein besonderer Zustand. Der weiß gar nicht, ob er sich in einer ISR befindet, oder nicht. Oliver
>[...] und merkt erst im Lauf der Implementierung, dass das garnicht so >kritisch ist. Wie wahr! >[...] kommen nun die Vorschläge, eine "dickere" Maschine zu benutzen. >Allerdings ohne auf mein Problem einzugehen. OK, dann hier noch ein Vorschlag, ohne auf Dein Problem einzugehen: Mach es doch mit Polling! Wie Du schon geschrieben hast, gibt es in Deinem System fünf Slaves und ein Datenpaket dauert 20 ms, wenn ich das richtig verstanden habe. Bleibt noch die Datenübertragungsrate (eine ganz unwesentliche Information). Ich nehme daher einfach mal an, dass in den 20 ms fünf Bytes = 40 Bits übertragen werden. Dann sieht meine kleine Beispiel-Machbarkeitsstudie dazu so aus: Bei genannten Übertragungsrate dauert ein Bit 0.5 ms. Eine vernünftige Abtastrate wäre dann z. B. 0.1 ms, d. h. die Signalleitungen müssen mit einer Frequenz von 10 kHz gepollt werden. Eine CPU mit 20 MHz ist 2000 mal höher getaktet, also hat man maximal 2000 Takte Zeit für die Auswerte-Statemachine. Da manche Instruktionen mehr als einen Takt benötigen, wollen wir mit 1500 Instruktionen rechnen. Geteilt durch die Slave-Anzahl 5 macht das immerhin 300 Instruktionen pro Slave. Abzüglich eines gewissen Anteils aufgrund von Overheads und weil der Prozessor wahrscheinlich auch noch was anderes tun soll, dürfen wir final von einem Kontingent von 200 Instruktionen zur Verarbeitung eines Übertragungsbits eines Slaves ausgehen. Nun sollte niemand unterschätzen, wieviel Power man in 200 Instruktionen packen kann, und andererseits muss man für ein Bit nur wenig machen: Pegel feststellen, Flankenwechsel erkennen, Timerstand auswerten, Timer runterzählen und gegebenfalls resetten, Ergebnisbit ins entsprechende Register shiften. Das ist alles mit einer kleinen Anzahl einfacher Instruktionen, die auf einer Handvoll Registern operieren, zu erledigen. Daher schätze ich die Chance, das bei einer Übertragungsrate in diesem Bereich tatsächlich so machen zu können, als durchaus realistisch ein - eine gute Implementierung der Statemaschine vorausgesetzt. Da benötigt man dann nur noch den Timer-Interrupt, der die 10 kHz Abtastfrequenz generiert. >Natürlich sind 20ms nicht viel. Ich habe hier aber ein System von 10 >Prozessen auf 6 Controllern, die völlig asynchron ablaufen. Und ich will >da eine Datenkonsistens von min. 2s realisieren. Und dieses Problem >besteht doch völlig unabhängig von den eingesetzten Komponenten. Bueno. Und wenn Du genau das jetzt mal im Detail so beschreiben würdest, dass man es auch versteht, dann würde wahrscheinlich auch endlich klar werden, wo Dein Problem wirklich liegt.
Oliver S. schrieb: > Eine Interrupt-Routine ist für den AVR kein besonderer Zustand. Der weiß > gar nicht, ob er sich in einer ISR befindet, oder nicht. das kann man ja ändern, in jeder AVR ISR könnte man ein Flag setzen mit einer zugehörigen Bitnummer, dann weiss man wo der AVR steckt, bzw. gerade war und danach auslesen.
Rainer V. schrieb: > So, nachdem wir nun gesehen haben, dass man von 200 CPU-Zyklen 2! > einsparen kann (natürlich nur, wenn man schlau ist...), kommen nun die > Vorschläge, eine "dickere" Maschine zu benutzen. Allerdings ohne auf > mein Problem einzugehen. > > Ich antworte jetzt ohne Zitate auf die für mich relevanten Beiträge! > > 1. Ja, es ist mir klar, dass die INterrupts eine Priorität haben. Und > nach neuerlichem Studium der Docs stellt sich mir wieder die Frage, ob > z.B. das Interrupt-Bit - etwa von Timer - auch gesetzt wird, wenn der > globale Interrupt nicht gesetzt ist. Wenn der globale Interrupt gesetzt > ist, dann wird doch wohl die entsprechende Routine angesprungen...wenn > nicht, dann wird die Routine eben nicht aufgerufen, ich wüßte aber > zumindest, das da ein Interrupt war oder??!! Im Wesentlichen ist das so. Ja. Das Interrupt-Flag (oder -Bit, wenn Du so willst) wird unabhängig davon gesetzt, ob der entsprechende Interrupt freigegeben ist, oder ob global alle oder kein Interrupt freigegeben ist. In der Dokumentation wird das nicht ausdrücklich so gesagt. Aber: In der gesamten Dokumentation wird auch das Gegenteil nicht gesagt. In der Dokumentation wird im wesentlichen gesagt, dass die Interrupt-Flags zu dem Zeitpunkt gesetzt werden, zu dem ihre Bedingung zutrifft oder das Ereignis eingetreten ist. Sie bleiben gesetzt, bis entweder die Interrupt-Routine ausgeführt wird, oder das Bit durch einen Befehl gelöscht wird. An das globale oder indiduelle Interrupt-Enable-Bit wird dabei keine Bedingung geknüpft. Das selbe Schema trifft im Allgemeinen (aber nicht grundsätzlich) zu: Was nicht ausdrücklich gesagt wird, trifft auch nicht zu. Oft sind die Aussagen aber über ein Datenblatt verteilt. Deswegen ist es manchmal nützlich zu einem Thema das gesamte Datenblatt durchzulesen. Z.B. in dem man in dem Datenblatt nach "Interrupt" sucht und alle Texte liest, in denen das Wort vorkommt. > 2. Wenn also mehrere Interrupts auflaufen, werden diese dann gemäß ihrer > Priorität ausgeführt. Jeweils direkt nach dem RETI des vorhergehenden? Nein. Es wird noch mindestens ein weiterer Befehl ausgeführt. Nämlich der Befehl, der dem folgt, während dessen Ausführung der Interrupt auftrat; der Befehl, dessen Adresse auf den Stack gespeichert wurde. Das ist hier aber schon mehrfach gesagt worden und steht auch in der Dokumentation. > 3. Natürlich sind 20ms nicht viel. Ich habe hier aber ein System von 10 > Prozessen auf 6 Controllern, die völlig asynchron ablaufen. Und ich will > da eine Datenkonsistens von min. 2s realisieren. Und dieses Problem > besteht doch völlig unabhängig von den eingesetzten Komponenten. Die beiden Dinge sind nicht völlig unabhängig voneinander. Sie hängen sogar eng zusammen. Das eine ist Deine Forderung. Eine Eigenschaft, die das Gesamtsystem erfüllen soll. Die Komponenten müssen aber auch in der Lage sein, diese Forderung zu erfüllen. Das ist das Andere. > [...]
LostInMusic schrieb: > Wie Du schon geschrieben hast, gibt es in Deinem System fünf Slaves und > ein Datenpaket dauert 20 ms, wenn ich das richtig verstanden habe. Danke für deine Mühe! Nein, du hast es eben nicht richtig verstanden. Die Slaves befinden sich jeweils für 20ms - und zwar auch völlig asynchron - in einem Prozess, der nicht unterbrochen werden darf...eben jeder Slave für sich (nebenbei hat auch jeder Slave zwei AD-Wandlungen zu managen. Das ist aber deutlich überschaubarer, glaube ich momentan noch :-)! Wenn der Master nun anklopft und Daten haben möchte, merkt der Slave das nicht und antwortet auch nicht. Wenn ich aber das Interrupt-Flag im Slave nach der Routine noch auswerten könnte, könnte ich dem Master dann trotzdem noch eine Nachricht schicken. Allerdings wäre die Unterbrechung der Slave-Routine schon "extrem" zeitkritisch. Immerhin müßte ich in deutlich unter 1ms ein Uart-Byte auswerten, damit der Slave sich überhaupt angesprochen fühlt. Bis dahin wäre der eigentliche Task aber komplett im Stillstand! Und als Slaves habe ich Arduino-Minis, die "nur" 4MHz Quarz haben. Insofern ist auch der Beitrag mit den 198 CPU-Takten nicht ganz am Thema vorbei. Ich bitte also die Helfe-Willigen, sich das Gesamtsystem noch mal vor die Augen zu führen. Ich will in min. 2s Daten von 5 Slaves bekommen. Dabei ist weder die Übertragungsrate der Ringleitung der Knackpunkt, sondern die Tatsache, dass ein Slave eben auf eine Anfrage nicht antwortet! Sicher wissen die Spezialisten ohne nachzudenken, wie man sowas löst...ich momentan noch nicht. So Leute, der Grill glüht...aber dank modernster Technik bleibe ich mit meinem Pad am Ball :-) Spätsommerlicher Gruß, Rainer
Rainer V. schrieb: > und ich hoffe doch stark, dass im Weltraum keine AVR's werkeln :-) Doch taten sie bis vor einem Jahr für ein Experiment auf der ISS. :) Inzwischen sind sie wieder auf der Erde.
Rainer V. schrieb: > Danke für deine Mühe! Nein, du hast es eben nicht richtig verstanden. > Die Slaves befinden sich jeweils für 20ms - und zwar auch völlig > asynchron - in einem Prozess, der nicht unterbrochen werden darf... Das genau ist das Problem. Dieser "Prozess" muss einfach unterbrechbar gemacht werden. Wenn er das nicht von Hause aus ist, war er von vornherein sowieso vollkommen beschissen programmiert. > jeder Slave für sich (nebenbei hat auch jeder Slave zwei AD-Wandlungen > zu managen. Was gibt es da groß zu "managen"? Normalerweise startet man die Wandlung und das war's. Irgendwann kommt dann ein Interrupt, der anzeigt, dass die Wandlung komplett ist, dann holt man das Ergebnis der Wandlung ab und gut isses. In der ganzen Zwischenzeit gibt es keinen Grund, die MCU schwachsinnigerweise damit zu beschäftigen, auf das Ende der Wandlung zu warten. Die kann da was anderes tun, nämlich z.B.: eine Anfrage des Masters zu verarbeiten...
Rainer V. schrieb: > Ist mir klar, weil du offensichtlich nur das liest, was du lesen > möchtest. Warum greifst du mich hier persönlich an? Habe ich dir was getan? OK, das kann ich auch... Wenn du genauso schlampig denkst, wie du deinen Aufbau beschreibst und so sieht es für mich aus, dann wundert mich nicht, dass du nicht mal im Ansatz weiter kommst, und allmählich sauer wirst. Da es schließlich an dir nicht liegen kann, wird jetzt auf denen rum getrampelt, die den wahren Wert deiner ach so genialen und vollständigen Erklärungen nicht erkennen können. Und Tschüss, viel Spaß und Erfolg ich dir wünsche, auf all deinen Irrwegen.
Arduino Fanboy D. schrieb: > Warum greifst du mich hier persönlich an? > Habe ich dir was getan? Hallo, ganz im Gegenteil. Ich lese deine Beiträge, auch wenn sie mir manchmal abstrus vorkommen! Und entspann dich mal...ich sitze in einer fröhlichen Runde im Garten...bald werde ich wahrscheinlich nicht mehr antworten können... c-hater schrieb: > Das genau ist das Problem. Dieser "Prozess" muss einfach unterbrechbar > gemacht werden. Wenn er das nicht von Hause aus ist, war er von > vornherein sowieso vollkommen beschissen programmiert. Ja Mann, diese Module sind uralt und sind sicher "beschissen" programmiert. Ich will sie aber benutzen! Und sie haben eben keine "Intelligenz". Sie schmeissen ihre Daten jede Sekunde raus, ob du sie nimmst oder nicht! Es kann ja auch sein, dass niemand mein Problem interessant findet...aber dann sagt das doch einfach. Gartengruß Rainer
>Wenn der Master nun anklopft und Daten haben möchte, merkt der >Slave das nicht und antwortet auch nicht. Wenn ich aber das >Interrupt-Flag im Slave nach der Routine noch auswerten könnte, könnte >ich dem Master dann trotzdem noch eine Nachricht schicken. Das ist schlicht dadurch zu lösen, indem Du den externen Interrupt enablest. Die Request-Leitung des Masters kommt an den entsprechenden Pin. Vor dem Eintritt in deine ununterbrechbare, 20 ms dauernde Routine deaktivierst Du alle Interrupts global mit "cli". Danach löschst Du das ExtInt-Pending-Bit manuell. Nach dem Ende der Routine schaust Du nach, ob es gesetzt ist. Wenn ja, hat der Master zwischendurch ein Anfrage geschickt und Du kannst sie beantworten. Dann löschst Du das ExtInt-Pending-Bit wieder manuell und zu guter Letzt aktivierst Du wieder alle Interrupts global mit "sei". Das ist alles. Das Pending-Bit wird vollautomatisch von der Hardware gesetzt, weil der externe Interrupt enabled ist. Eine ISR für den ExtInt ist überflüssig; sie würde niemals angesprungen werden. Oder ganz schick und wenn Du noch einen Timer mit Capture-Interrupt frei hast: Dasselbe damit machen; dann kannst Du sogar den Zeitpunkt auslesen, wann der Master den Request geschickt hat.
Rainer V. schrieb: > Ja Mann, diese Module sind uralt und sind sicher "beschissen" > programmiert. Dann ändere das einfach. Wo ist das Problem? > Ich will sie aber benutzen! Das ergibt absolut keinen Sinn!
Nachtrag - es gibt natürlich eine noch billigere Lösung: Der Master hält den Pegel auf der Request-Leistung einfach länger als 20 ms. Dann bekommt es der Slave garantiert immer mit. Sobald er geantwortet hat, setzt der Master die Leitung wieder auf "Idle".
LostInMusic schrieb: > Der Master hält > den Pegel auf der Request-Leistung einfach länger als 20 ms. Ja, danke, das hätte was, wenn es nur einen Slave gäbe...if you see...und ich schrieb auch schon, dass ich eine RS422-Halb-Duplex verwenden will. Das Problem sind doch die völlig asynchronen Vorgänge! Und ich habe eben vorgegeben, dass ich nicht unendlich warten will, bis ich einmal alle Datensätze aufgesammelt habe. c-hater schrieb: > Das ergibt absolut keinen Sinn! Lieber Freund...es ergibt einfach deshalb Sinn, weil ich es will! Du sitzt hier nicht in einem Meeting, wo du einfach sagst, ich bin raus...Dann antworte doch einfach nicht mehr. Das ist genauso wie "raus" und ich bin dir nicht böse... Gruß Rainer
Rainer V. schrieb: > Lieber Freund...es ergibt einfach deshalb Sinn, weil ich es will! Aha. Das trotzige Aufstampfen eines unverständigen Kindes. Bei einem Kind ist das zumindest verständlich, das weiß es einfach noch nicht besser. Du aber bist erwachsen. D.h.: man kann das nur so deuten: Stockedoof und stolz darauf. Jegliches Hinzulernen ausgeschlossen, weil garnicht gewollt... > Dann antworte doch einfach nicht mehr. Werde ich tun.
>dass ich eine RS422-Halb-Duplex verwenden will. >Das Problem sind doch die völlig asynchronen Vorgänge! Auch mit diesen Infos bleibt für mich im Dunkeln, wo der Kern Deines Problems liegt. Ist es so schwer, das einfach mal mit ein paar lupenreinen, verständlichen Sätzen auf den Punkt zu bringen? Es wäre wirklich hilfreich (für Dich!). Was muss der Master können? Was können die Slaves schon und was sollen sie noch können müssen? Was ist festgelegt und was kannst Du ändern? Welchen Randbedingungen unterliegt das ganze System? Du solltest vielleicht auch nicht davon ausgehen, dass jeder mit RS422-Halb-Duplex vertraut ist. Bevor das alles nicht geklärt ist, ist jede weitere Diskussion nur Stochern im Nebel.
LostInMusic schrieb: > Ist es so schwer, das einfach mal mit ein paar > lupenreinen, verständlichen Sätzen auf den Punkt zu bringen? Offensichtlich ja. Aber vermutlich sind die geheimen Module so geheim, dass die Welt ins wanken gerät, wenn wir was darüber erfahren würden. > RS422-Halb-Duplex Alleine das ist schon unüberlegt, würde ich mal vermuten.... Denn die RS422 Spezifikation gibt das nicht her. LostInMusic schrieb: > Du solltest vielleicht auch nicht davon ausgehen, dass > jeder mit RS422-Halb-Duplex vertraut ist. OK, vielleicht bin ich auch nur nicht damit vertraut. Denn bisher dachte ich, dass genau das der Kern Unterschied zu RS485 ist, da dieses eine Kollision locker weg steckt. > Arduino-Minis, die "nur" 4MHz Quarz haben. Als eingewiesene Arduino Fachkraft, mit fundiertem Halbwissen, kenne ich nur 16MHz und 8MHz Arduino Minis. Aber Wunder gibts ja immer wieder....
Interessant wäre ja auch mal, zu erfahren, was das für ein geheimnisvoller Sensor ist, der es nötig macht, zur Kommunikation 20ms lang mit ihm, in einem Zeitraster von 1/(4 MHz) = 250 ns zu reagieren. Ich hänge mich jetzt mal aus dem Fenster: Ich halte es eher für unwahrscheinlich , dass das nötig ist. Wahrscheinlicher wird man auf Flanken oder die Zeitdauer zwischen Flanken reagieren müssen. Das ist etwas ganz Anderes. Dazwischen tippt der AVR noch bei den Affen am monumentalen Weltbestseller mit und langweilt sich dabei. Bei mal so geratenen 8 Bit Sensordaten sind das immer noch so 5.000 (in Worten Fünftausend) Befehle zwischen jedem Bit). Seien es 32 Bit, so ergeben sich immer noch 1250 Befehle. Das ist reichlich . Ob meine Vermutungen so richtig sind, mag der TO vielleicht bestätigen oder bestreiten. Aber bitte mit Fakten, d.h. mit Angabe von Typ und Link zum Datenblatt des Sensors. Falls da nichts kommt, warten wir dann mal auf den "Spezialisten" mit dem Zauberstab. Der wird das alles ohne Informationen klären. Einfach weil er Spezialist ist. Chuck Norris, z.B. erledigt solche Sachen einfach durch Muskelkraft und ein böses Gesicht. :-)
Beitrag #6410218 wurde vom Autor gelöscht.
Theor schrieb: > warten wir dann mal auf den "Spezialisten" mit dem Zauberstab. https://www.youtube.com/watch?v=BKorP55Aqvg X: "What keeps you from doing it?" E: "Geometry." X: "Then just ignore it!" Einfach unübertroffen.
:
Bearbeitet durch User
Rainer V. schrieb: > Wenn während einer laufenden Interrupt-Routine > weitere Interrupts auftreten, dann werden die aber nicht verworfen, > sondern offensichtlich gespeichert. Es muss dir aber klar sein, dass nur der Interrupt selbst "gespeichert" wird, und nicht die Zustände, die dazu führen. D.h. wenn zwei Slaves gleichzeitig serielle Daten auf die gleiche Schnittstelle schicken und das zu zwei Interrupts führt (muss nicht), sind die Daten trotzdem kaputt, ohne dass du es notwendigerweise bemerkst.
Hallo Rainer, mal ehrlich, die letzten Infos hättest du schon früher bringen können. Das musst du einsehen. Deine Info ist. Du hast 5 Slaves, wo jeder Slave zu x beliebigen Zeitpunkt für 20ms auf keine serielle Anfrage reagiert. Das wiederholt sich pro Slave aller einer Sekunden. Du möchtest innerhalb von 2s alle Slave abgefragt haben. Jetzt überlegen wir einmal. Der Worst-Case ist wenn jeder Slave genau dann mit seiner 20ms Blockierung beginnt wenn du diesen abfragen möchtest. Das heißt du verlierst insgesamt mindestens 100ms. Wenn sich das aller 1s wiederholt, hast max. 900ms Zeit für die gesamte Kommunikation mit allen. An der Stelle wäre es wichtig zu wissen mit welcher Baudrate du kommunizierst und wieviele Bytes übertragen werden müssen. Dafür ist ein definiertes Übertragungsprotokoll wichtig zu kennen bzw. aufzustellen. Es könnte ja sein du überträgst massig Daten wofür 900ms nicht ausreichen. Soviel zum Thema fehlende Informationen. Das solltest du dir nochmal genau überlegen. Oder du musst dann allein weitermachen. Ich mach mal weiter. Wenn der Master mit einem angenommenen Timeout von 5ms seine Anfrage wiederholt, verlierst du im Worst Case maximal 5ms, wenn die letzte Anfrage auf das Ende der 20ms ISR Blockade trifft. Das heißt 5 Slaves mal 25ms Totzeit = 125ms. Restzeit 875ms. Das heißt weiter du hast 875ms / 5 = 175ms Zeit für die zur Kommunikation pro Slave. Jetzt bist du dran. Wieviele Bytes überträgst du und welche Baudrate ist dafür notwendig damit du noch Luft hast und nicht auf Kante nähst. Wenn es eng wird kannste noch mit dem Timeout von 5ms runtergehen. Mit den Zahlen bzw. Überlegung musste jetzt rumspielen. Wenn das klar ist, fängste an mit definierten Protokoll eine Kommunikation zu programmieren. Anfrage senden und auf Antwort warten ggf. Anfrage wiederholen. Da haste schon einmal zu tun.
c-hater schrieb: > Man muss einfach nur wissen, was man tut. Du weißt das definitiv immer > noch nicht (nach so vielen Jahren: schändlich, weil nix dazu gelernt)! c-hater schrieb: > Takte. Ein gelernter Assemblerprogrammierer kann in 190 Takten eine > Menge Zeug tun... > > Du nicht! Du auch nicht. Wenn so eine Aussage von jemandem kommt, der nicht mal weiss welche Register beim AVR als Paare bezeichnet werden... Wenn ich mich richtig erinnere waren für dich r25/r26 ein Register- paar...
Rainer V. schrieb: > Selbst wenn ich die Zeit, in der alle Slaves ihre Daten übermittelt > haben müssen, auf 2s lege, muß ich doch quasi 6 asynchrone Ereignisse, > die sich alle irgendwie blockieren können, in dieser Zeit "geschafft" > haben. Muß mangels Hardware jetzt noch mal genauer in das Timing des Dann mach doch mal einen Round-robin System. Master sendet alle 2 Sekunden eine Nachricht mit Adresse 0xFF - (an alle Slaven) mit Masterzeit (Sekunden und milisekunden) und dazu 1 zusätzlicher Byte, wo jedes gesetztes bit bedeutet, daß in den letzten 2 Sekunden eine Nachricht von diesem Slave empfangen wurde. Jeder Slave hat seine Timeslice, in welcher er eine neue Nachricht rausschickt oder die letzte wiederholt, falls seine vorherige Nachricht nicht empfangen, d.h. sein bit nicht gesetzt wurde. Slave 1 hat nun 200ms Zeit, von 1-200, Slave 2 hat Zeit von 201-400, Slave 3 von 401-599ms etc. Und wenn es 2 Sekunden sind, hat Slave 1 noch einmal die Möglichkeit von 1001-1200 die Nachricht zu wiederholen, wenn es aus irgendeinem Grund vorher nicht geklappt hat, Slave 2 hat diese Möglichkeit von 1201-1400, Slave 3 von 1401-1600 etc. Punkt ist: Selbst wenn ein Slave nicht sofort antworten kann, hat er doch die Synchron Nachricht erhalten (hoffentlich geschieht der Empfang per ISR) und kann seine TimeSlice ausrechnen und entsprechend antworten. Die blockierende Routine dauert max. 20ms, dementsprechend ist es überhaupt kein Problem seine Antwort in diesen 200ms zu senden.
Marc V. schrieb: > Du auch nicht. Ich denke schon. Vermutlich denkt das auch jeder andere kompetente Mitleser, was deinen Kompetenzstatus zumindest etwas "anrüchig" macht... Dazu kommt, dass ich mindestens zwei nichttriviale Asm-Projekte veröffentlicht habe, du hingegen exakt 0... > Wenn so eine Aussage von jemandem kommt, der nicht mal weiss welche > Register beim AVR als Paare bezeichnet werden... Im Prinzip kann ich jede Sammlung von zwei Registern als Paar bezeichnen, denn das primäre Kennzeichen eines Paars ist EINZIG, dass es aus zwei Elementen besteht. Aber natürlich macht es es beim AVR8 Sinn, bevorzugt Register zu Paaren zusammen zu fassen, die erstens im Registerfile aufeinander folgen und von denen zweitens das Register mit dem geringeren Index einen "even"-Index hat. Das sind dann spezielle Registerpaare, die besondere Eigenschaften besitzen. Insbesondere natürlich die, dass sie sich anderen dieser besonderen Paare mittels movw innert eines Taktes zuweisen lassen. Wie du dich leicht überzeugen kannst, nutze ich dieses Feature in meinem Programmen ziemlich intensiv... Einige dieser Paare haben darüber hinaus noch weitere besondere Eigenschaften. Auch das nutze ich natürlich, denn das geht ja kaum anders, wenn man mit indizierte Adressierung operiert...
c-hater schrieb: > Dazu kommt, dass ich mindestens zwei nichttriviale Asm-Projekte > veröffentlicht habe, du hingegen exakt 0... Bitte ein link auf entsprechende Beiträge... > Im Prinzip kann ich jede Sammlung von zwei Registern als Paar > bezeichnen, denn das primäre Kennzeichen eines Paars ist EINZIG, dass > es aus zwei Elementen besteht. Sicher. Dann benutzt du auch SREG und r3 als ein Paar? > Insbesondere natürlich die, dass sie sich anderen dieser besonderen > Paare mittels movw innert eines Taktes zuweisen lassen. Sicher. Wie z.B. r25/r26? > Wie du dich > leicht überzeugen kannst, nutze ich dieses Feature in meinem Programmen > ziemlich intensiv... Naja. Deine Programme habe ich zwar noch nie gesehen, aber wenn du es behauptest... BTW bei Copy&Paste kann man auch schwer derartige Fehler machen...
Marc V. schrieb: > Dann benutzt du auch SREG und r3 als ein Paar? SREG ist kein MCU-Register, sondern SFIO. Es macht wohl eher selten Sinn, ein spezialisiertes SFIO zusammen mit einem MCU-Register als Paar zu verwenden. Aber sogar sowas könnte vorkommen. Z.B. TCNTirgendwas+Zählererweiterung in einem MCU-Register. > Bitte ein link auf entsprechende Beiträge... Suche in "Projekt & Code" nach "ATtiny85". Die Suche liefert recht wenige Ergbnisse. Zwei davon sind von mir. Und, bevor du fragst: ja, ich verwende durchaus auch andere AVR8... Veröffentlicht habe ich nur die Buddelschiffe. Sachen, die erstens reine Spielereien sind (also insbesondere nicht die Interessen meines Brötchengebers tangieren), und die zweitens zeigen, was selbst auf kaum wahrnehmbaren µC geht, wenn ihnen direkt in der Sprache was beibringt, die sie wirklich verstehen...
c-hater schrieb: >> Bitte ein link auf entsprechende Beiträge... > > Suche in "Projekt & Code" nach "ATtiny85". Die Suche liefert recht > wenige Ergbnisse. Zwei davon sind von mir. Nööö, selber suchen, link senden. Ein Beitrag von dir, (Audio Spektrum Analyzer mit ATtiny85) habe ich zwar gefunden, aber nachdem ich disassembliertes .HEX File gesehen habe, behaupte ich, daß es ein abgeschriebenes Programm (wahrscheinlich in BASIC) ist, mehr als BASIC hast du bestimmt nicht gelernt... Beispiel:
1 | sub r0, r0 |
2 | sub r1, r1 |
Lol. So macht das nur der compiler, jemand der selber in Assembler schreibt und Ahnung hat, benutzt hier wahrscheinlich:
1 | clr r0 |
2 | clr r1 |
P.S. An deiner Stelle wurde ich schnellstens aufhören andere Leute anzuspucken und ständig etwas von Copy&Paste zu plappern...
:
Bearbeitet durch User
Marc V. schrieb: > und Ahnung hat, benutzt hier wahrscheinlich: > clr r0 ... was EOR r0,r0 entspricht. Also nur langsam schreiben. leo
Marc V. schrieb: > sub r0, r0 ist aber nicht Marc V. schrieb: > clr r0 da darf es doch Unterschiede geben und wer sich auskennt nutzt auch mal miese Tricks wenn die Takte bekannt sind und auch erst Recht gewünscht sind. Man könnte ja auch ein NOP einfügen, ist aber ein Befehl mehr, nur das muss man halt wissen ob der eine Befehl noch reinpasst oder das gewünschte Ergebnis in clocks bringt!
leo schrieb: > ... was EOR r0,r0 entspricht. Was ja auch in DaBla steht:
1 | Operation: |
2 | (i) Rd ← Rd ⊕ Rd |
> Also nur langsam schreiben.
Du und andere "Experten" auch...
Marc V. schrieb: > So macht das nur der compiler, jemand der selber in Assembler > schreibt und Ahnung hat, benutzt hier wahrscheinlich: > clr r0 > clr r1 clr ist kein AVR ASM Statement, sondern ein Pseudobefehl des Assemblers Codeidentisch mit eor r0, r0 eor r1, r1 Zudem werden andere Flags gesetzt, als bei sub r0, r0. Es macht also schon einen Unterschied. Du vergleichst Äpfel mit Birnen.
Joachim B. schrieb: > da darf es doch Unterschiede geben und wer sich auskennt nutzt auch mal Ja. Nur gibt es hier keine Unterschiede, ausser in bestimmten Flags aber da es sich nur um einen Register handelt, kann es diese Unterschiede nicht geben. > Man könnte ja auch ein NOP einfügen, ist aber ein Befehl mehr, nur das Man könnte ja auch zehn NOPs einfügen, nur wozu?
:
Bearbeitet durch User
Arduino Fanboy D. schrieb: > Zudem werden andere Flags gesetzt, als bei sub r0, r0. > Es macht also schon einen Unterschied. > Du vergleichst Äpfel mit Birnen. Ausser Zero-Flag wird kein anderer Flag gesetzt. Und nochmal für dich, da du ja auch ein "Experte" zu sein scheinst: Bei sub r0, r0 macht es keinen Unterschied, da ausser Zero-Flag kein anderer Flag gesetzt wird, es werden aber ein paar zurückgesetzt, die aber im weiterem Verlauf des kopierten Programms gar nicht gebraucht werden. Um das zu verstehen, muss man aber Assembler können, was bei dir offensichtlich nicht der Fall ist... P.S. Disassembler übersetzen CLR immer mit EOR r,r aber sub rx, rx zweimal hintereinander benutzen nur compiler.
:
Bearbeitet durch User
Beim RS485/422 Konzept geht es am Einfachsten ohne irgendwelche Umständen bei der Slave Programmierung mit einem adressierbaren Master/Slave Konzept. Jeder Sklave muß absolut die Schnauze halten bis er ein auf ihn bezogene Adressierung erhält. Dann braucht der Master nur der Reihe nach die Sklaven ansprechen. Dann gibt es keine Kollisionen. Alle anderen Sklaven halten sich stillschweigend zurück. So machten wir es in der Vergangenheit in einem älteren industriellen System. Das hat über Dekaden sehr zuverlässig funktioniert. Alle Datenaustausche sind mit CRC16 abgesichert. Wenn aus irgendeinen Grund der adressierte Sklave nicht antwortet, dann weiß sich der Master mit Retry oder anderen hier vorgesehenen Ausweichstrategien zu helfen. Was bei RS485 ganz wichtig ist die Sklaven mit einem zuverläßigen Watchdog/HW Schutz auszustatten damit der Bus durch einen abgestürzten Sklaven nicht möglicherweise blockiert werden kann. Z.B kann man mit einem HW One-Shot Timer bei der Sklavensendesteuerung verhindern, daß der Bus durch ein Versagen des uC blockiert wird. Für den Nicht-industriellen Einsatz ist dies in vielen Fällen vollkommen ausreichend. Jedenfalls sind bei den Sklaven bei der Programmierung sonst keine besonderen Timing Rücksichten oder komplizierte Protokolle notwendig. Bei Hobbyanwendungen ist dieses Konzept auf alle Fälle zuverlässig genug. Die bisherigen Erfahrungen bewiesen das. Wer besonders hohe Zuverlässigkeit braucht oder Service Requests von den Sklaven muß eben auf andere Möglichkeiten wie z.B. CAN, ARINC oder andere komplizierte industrielle Protokolle und Busse zurückgreifen. Für den Hausgebrauch kann man oft mit den hier vorgeschlagenem bescheidernen Konzepten auskommen.
Marc V. schrieb: > Um das zu verstehen, muss man aber Assembler können, was bei dir > offensichtlich nicht der Fall ist... Mangelhafte Auffassungsgabe mit Angriffen kompensieren zu wollen... Armselig. Vielleicht bin ich ja wirklich nicht der Oberheld in Sachen ASM. Aber deinen Ausführungen kann ich entnehmen, dass es dicke reicht dich mehrfach zu übertrumpfen. Du hast mein volles Mitleid.
Marc V. schrieb: > Man könnte ja auch zehn NOPs einfügen, nur wozu? hat man früher mal für ein exaktes Timing gemacht, als RAM und ROM noch Mangelware war! Arduino Fanboy D. schrieb: > clr ist kein AVR ASM Statement guter Hinweis, ich bin darauf reingefallen, aber meine ASM Kenntnisse sind alt und nicht beim AVR speziell vorhanden! Marc V. schrieb: > Disassembler übersetzen CLR immer mit EOR r,r aber sub rx, rx > zweimal hintereinander benutzen nur compiler. so langsam scheint mir hier reden einige von popobacken und andere von kuchenbacken. Keine Ahnung wer sich hier nun selber outet, ausser ich :) wie gesagt ich habe von AVR ASM keine große Ahnung, nur rudimentär das es ld lda oder sowas gibt! interessant bleibt das einer schreibt es gibt keinen ASM clr, ich denke ja auch register werden gelöscht in dem 0 reingeschrieben wird, aber mit sich selber subtrahiert ist schon "komisch" andererseits Marc V. schrieb: > sub rx, rx > zweimal hintereinander ist mindestens genauso komisch
Beitrag #6411392 wurde vom Autor gelöscht.
Marc V. schrieb: > sub r0, r0 > So macht das nur der compiler, Also avr-gcc generiert solchen Code schon mal nicht, und in der libgcc (asm) gibt's sowas auch nicht. > schreibt und Ahnung hat, benutzt hier wahrscheinlich: > clr r0 Das setzt andere Flags (Z), SUB hingegen setzt alles an Arithmetik-Flags (alle außer I und T).
Marc V. schrieb: > habe, behaupte ich, daß es ein abgeschriebenes Programm (wahrscheinlich > in BASIC) ist, mehr als BASIC hast du bestimmt nicht gelernt... Das sind gleich zwei ziemlich verwegene Behauptungen. Du kannst sie hoffentlich mit irgendwelchen Beweisen untermauern. > Beispiel: >
1 | > sub r0, r0 |
2 | > sub r1, r1 |
3 | >
|
Ja, das kommt sogar mehrfach vor. Immer da, wo ich mein size-optimiertes MUL8x8-Macro benutzt habe (was ich auch schonmal irgendwo hier veröffentlicht habe). OK, das erste sub müßte an dieser Stelle nicht sein, sondern könnte genausogut z.B. ein xor r0,r0 (AKA: clr R0) sein, das zweite hingegen ist für den Rest der Routine essentiell wichtig. Sie würde nicht korrekt funktionieren können, wenn das nicht mit sub gelöst worden wäre. Du unsäglicher nixwissender aber nichtsdestotrotz überaus arroganter Blindflansch bist einfach nur viel zu doof, den Kontext zu kapieren...
Arduino Fanboy D. schrieb: > Aber deinen Ausführungen kann ich entnehmen, dass es dicke reicht dich > mehrfach zu übertrumpfen. > > Du hast mein volles Mitleid. Lol. Weil du keine Ahnung hast. Für solche, die doch Ahnung haben ist ein File angehängt in welchem nebeneinander zwei völlig identische Teie des Codes auf zwei verschiedenen Adressen stehen. c-hater schrieb: > Du unsäglicher nixwissender aber nichtsdestotrotz überaus arroganter > Blindflansch bist einfach nur viel zu doof, den Kontext zu kapieren... Wenn das excellente programmierkenntnisse sind, dann habe ich wirklich keine Ahnung... Link: Beitrag "Re: Audio Spektrum Analyzer mit ATtiny85"
Johann L. schrieb: > Marc V. schrieb: >> sub r0, r0 >> So macht das nur der compiler, > > Also avr-gcc generiert solchen Code schon mal nicht, und in der libgcc > (asm) gibt's sowas auch nicht. Anmerkung: In der avr-libgcc gibt es vergleichbaren Code, aber nicht den gleichen :-) Zum Beispiel in __udivmodhi4 und __udivmodsi4 SUB r26, r26 SUB r27, r27
Marc V. schrieb: > ist ein File angehängt in welchem nebeneinander zwei völlig > identische Teie des Codes auf zwei verschiedenen Adressen stehen. Sowas machen auch doofe Compiler wenn sie optimieren, z.B. bei Inlining oder Loop Unrolling. Insbesondere bei Optimierung auf Geschwindigkeit.
Marc V. schrieb: > Für solche, die doch Ahnung haben ist ein File angehängt in welchem > nebeneinander zwei völlig identische Teie des Codes auf zwei > verschiedenen Adressen stehen. Das passiert bei der Verwendung von Macros schon mal und ist überaus sinnvoll, wenn auf Peformance optimiert wird. Denn es spart den vergleichweise teuren Callframe... Macht ein richtig guter C-Compiler übrigens ganz genauso...
c-hater schrieb: > Macht ein richtig guter C-Compiler übrigens ganz genauso... Ach, mach dir keinen Kopp darum.... Mich ist der Marc V. vor einiger Zeit genauso verbohrt angegangen. Da war es ihm wichtig, zu behaupten, dass I2C Adressen 8 Bit haben. Ihm wollte das R/W Bit der Adresse zurechnen. Hinweise auf irgendwelche Datenblätter und die I2C Spezifikation waren ihm komplett egal.
Johann L. schrieb: > Marc V. schrieb: >> ist ein File angehängt in welchem nebeneinander zwei völlig >> identische Teie des Codes auf zwei verschiedenen Adressen stehen. > > Sowas machen auch doofe Compiler wenn sie optimieren, z.B. bei Inlining > oder Loop Unrolling. Insbesondere bei Optimierung auf Geschwindigkeit. Stimmt. Nur bei soviel code wie oben fällt ein rcall+ret (7 Takte) kaum ins Gewicht. Aber 166 zusätzliche Bytes schon... c-hater schrieb: > Das passiert bei der Verwendung von Macros schon mal und ist überaus > sinnvoll, wenn auf Peformance optimiert wird. Denn es spart den > vergleichweise teuren Callframe... Ja, 7 Takte und 0,875us (bei 8MHz Tiny) einsparen aber 166 Bytes verschwenden - einfach genial... > Macht ein richtig guter C-Compiler übrigens ganz genauso... Dachte, du hast das selber in ASM geschrieben? Wenn es C-Compiler genauso machen, wo hast du dann deine genialen Kenntnise in Assembler benutzt und wozu?
Marc V. schrieb: > Nur gibt es hier keine Unterschiede, ausser in bestimmten Flags Ja genau... Mehr oder weniger zufällig ist nun gerade bei dieser Routine der Zustand des carryflags für den weiteren Fortgang der Sache relevant. Und der Sinn der Anwendung der sub-Instruktion ist hier halt, in einem Takt sowohl das Register zu clearen als auch das Carry-Flag zu löschen. An solchen "Tricks" erkennt man gelernte Assembler-Programmierer. (Naja: auch gute Codegeneratoren von Compilern, denn auch die werden letztlich natürlich auch von guten Assemblerprogrammierern verfasst...) Du bist auf jeden Fall absoluter Nullwisser-Arsch. Und du scheinst auch nicht dazulernen zu wollen. Übrigens: hattest du mal ein Alias "Ossifant"? Würde ziemlich gut passen... Naja, du wirst es natürlich abstreiten, die Moderatoren könnten es wohl rausfinden, werden ihre Erkenntnisse aber keinesfalls veröffentlichen. Egal, soll sich jeder Leser sein eigenes Bild machen...
Marc V. schrieb: > Stimmt. > Nur bei soviel code wie oben fällt ein rcall+ret (7 Takte) kaum ins > Gewicht. Der Nutzcode des MUL8X8-Macros hat 40 Takte. 7 Takte mehr für einen Callframe bedeutet einen Overhead von 7*100/40=17,6%. Du dummer Blindflansch kannst nichtmal trivialste Mathematik. Du bist so prasseldumm, dass es einen Hund jammert... > Ja, 7 Takte und 0,875us (bei 8MHz Tiny) einsparen aber 166 Bytes > verschwenden - einfach genial... Die Lösung funktioniert insgesamt auch deshalb, weil ich Size- und Performance-Optimierung weise gemischt habe. Das ist, wozu ein C-Compiler heute leider noch nicht selbstständig fähig ist. Bestenfalls kann man ein wenig nachhelfen. Bezüglich der (sehr trivialen) Mathematik in dem Programm könnte ich dem GCC das schon relativ problemlos beibiegen. Aber der Rest ist Sackstand. Letztlich liefe es darauf hinaus, das halbe Programm doch wieder in Asm zu schreiben (mit der unsäglich grottigen gcc-Inkarnation dieser eigentlich einfachen, übersichtlichen und schönen Sprache). Und dann am Ende immer noch nicht so effizient zu sein, wie mein natives Asm-Programm... > Dachte, du hast das selber in ASM geschrieben? Habe ich. > Wenn es C-Compiler genauso machen Sie versuchen es. Mit eher mäßigem Erfolg...
c-hater schrieb: > des carryflags für den weiteren Fortgang der Sache relevant. Und der > Sinn der Anwendung der sub-Instruktion ist hier halt, in einem Takt > sowohl das Register zu clearen als auch das Carry-Flag zu löschen. Aha. Gleich zweimal hintereinander, wie es auch zufälligerweise Compiler tun? > Du bist auf jeden Fall absoluter Nullwisser-Arsch. Und du scheinst auch > nicht dazulernen zu wollen. Wenn Argumente nicht vorhanden sind, kommen Beleidigungen... Und wenn du behauptest, diesen armseligen Stück (abgeschriebenen Code) selbst in Assembler geschrieben zu haben, dann hast du entweder keine Ahnung von programmieren oder du hältst alle anderen für Idioten. > An solchen "Tricks" erkennt man gelernte Assembler-Programmierer. An welchen Tricks? 166 Bytes bei 8KB verschwenden? Hör auf, unnötig einen noch grösseren Idioten als du schon bist aus dir zu machen. > Übrigens: hattest du mal ein Alias "Ossifant"? Würde ziemlich gut > passen... Nein, natürlich nicht. Auch melde ich mich nicht als Gast an, wie es einige hier tun...
c-hater schrieb: > Der Nutzcode des MUL8X8-Macros hat 40 Takte. 7 Takte mehr für einen > Callframe bedeutet einen Overhead von 7*100/40=17,6%. > > Du dummer Blindflansch kannst nichtmal trivialste Mathematik. Du bist so > prasseldumm, dass es einen Hund jammert... Wie ich schon sagte, hör auf, unnötig einen noch grösseren Idioten als du schon bist aus dir zu machen. Wie willst du 83 Befehle in 40 Takte packen? Du bist ganz einfach ein Idiot der nicht mal rechnen kann.
Marc V. schrieb: > Wie willst du 83 Befehle in 40 Takte packen? Woher nimmst du die 83 Befehle? Das MUL8X8-Macro umfaßt jedenfalls nur 40 Takte.
Marc V. schrieb: > Gleich zweimal hintereinander, wie es auch zufälligerweise Compiler > tun? Die tun es vermutlich aus demselben Grund aus dem ich es getan habe: Sieht hübscher aus. Sprich: der Verfasser des Codegenerators (zumindest des hier relevanten Teils davon) hat wohl ähnliche Schönheitsideale wie ich. Und nein, Ossifant, du kriegst den Quelltext nicht. Weil du dermaßen prasseldoof und gleichzeitig unerträglich arogant bist. Wenn du nämlich wenigstens einigermaßen clever wärst (also wenigstens einen gewissen substantiellen Grund für die Arroganz hättest), hättest du das längst aus dem VB.net-Code extrahieren können. Da ist nämlich eine Quasi-1:1-Umsetzung des Asm-Codes für den Tiny in VB.net enthalten. Der im Thread erwähnte "Simulator", mit dessen Hilfe die hübschen bunten Grafiken aus dem Thread in akzeptabler Zeit produziert werden konnten... Wenn VB.net nicht dein Ding ist: das .net-Zeug ist naturgemäß CLI-Code, du kannst dir das also auch problemlos in der C#-Entsprechung ausgeben lassen. Oder kannst du auch das nicht? Kannst du überhaupt irgendetwas? Außer inkompetent rumzulabern? Das kannst du immerhin ganz gut...
c-hater schrieb: > Woher nimmst du die 83 Befehle? Glaube zwar nicht, daß du da etwas verstehen wirst, aber hier: Beitrag "Re: Verständnis AVR Interrupts" c-hater schrieb: > Und nein, Ossifant, du kriegst den Quelltext nicht. Man, sowas nennt sich Paranoia - schon mal nach Hilfe gesucht? > Wenn VB.net nicht dein Ding ist: Nein, ist es nicht, aber wir sind uns wenigstens in einem einig: Weiter als Basic bist du nicht gekommen. > Außer inkompetent rumzulabern? Das kannst du immerhin ganz gut... Und kannst du etwas anderes außer beleidigen und Fragen ausweichen?
:
Bearbeitet durch User
Arduino Fanboy D. schrieb: > Ach, mach dir keinen Kopp darum.... > Mich ist der Marc V. vor einiger Zeit genauso verbohrt angegangen. > Da war es ihm wichtig, zu behaupten, dass I2C Adressen 8 Bit haben. Lügen auch noch? Ich habe nie behauptet, daß die Adresse 8 bit hat - nur daß es die oberen 7 bits sind. Ich habe aber behauptet, daß es deswegen Blödsinn ist, jedesmal die Adresse rumzuschieben und dann noch mit R/W bit zu OR-en, anstatt am Anfang eine Adresse für schreiben und eine fürs lesen zu definieren - und das wars dann.
Marc V. schrieb: > c-hater schrieb: >> Sinn der Anwendung der sub-Instruktion ist hier halt, in einem Takt >> sowohl das Register zu clearen als auch das Carry-Flag zu löschen. > > Gleich zweimal hintereinander, wie es auch zufälligerweise Compiler > tun? Der obige asm-Code mit den beiden SUBs aus der avr-libgcc ist nicht vom Compiler sondern von Chertykov soweit ich weiß. avr-gcc selbst generiert sowas nicht. c-hater schrieb: > An solchen "Tricks" erkennt man gelernte Assembler-Programmierer. Sowas überlegt man sich in 5 Sekunden selber wenn man's braucht. Peinlich, das überhaupt zu erwähnen...
Marc V. schrieb: > Ich habe nie behauptet, daß die Adresse 8 bit hat Ist klar... Marc V. schrieb: > Lügen auch noch? Das überlasse ich lieber dir. Klar, ist dir die Blamage von damals Höllen peinlich. Habe ich volles Verständnis für. Aber raus kommst du da nicht mehr. Den Pranger hast du dir selber gesucht und dich selber dran gestellt.
Arduino Fanboy D. schrieb: > Klar, ist dir die Blamage von damals Höllen peinlich. Welche Blamage, pathologischer Lügner? > Habe ich volles Verständnis für. > Aber raus kommst du da nicht mehr. > Den Pranger hast du dir selber gesucht und dich selber dran gestellt. Geh zum c-hater und dann beide ganz schnell zum Psychiater.
Sehr geehrte Damen und Herren, freuen Sie sich auf die nächste Folge von "How to destroy a thread", die wir in Kürze ausstrahlen.
Johann L. schrieb: > die nächste Folge Obwohl es sehr schwer wird, das zu toppen was hier abgeliefert wurde :)
c-hater schrieb: > Dazu kommt, dass ich mindestens zwei nichttriviale Asm-Projekte > veröffentlicht habe Genau genommen - eines. Das Andere kann man sich aus den Hex-Files / den .NET-Files decompilieren oder das veröffentlichte Decompilat (eines AVR-Hex-Files) als "Veröffentlichung" studieren :-). Habe ich etwas übersehen?
:
Bearbeitet durch User
Hallo und danke...besonders auch für die lustigen Beiträge...die Schnittstellenbausteine sind eingetroffen. Leider hakt das Programm für die Slaves noch etwas. Ich denke aber, dass ich morgen einen ersten Test mit Master und Slave laufen lassen kann. Werde dann weiter berichten. Gruß Rainer
900ss D. schrieb: > Johann L. schrieb: >> die nächste Folge > > Obwohl es sehr schwer wird, das zu toppen was hier abgeliefert wurde :) W.S. fehlt noch, dann ist das zu toppen!
Johann L. schrieb: > c-hater schrieb: >> An solchen "Tricks" erkennt man gelernte Assembler-Programmierer. > > Sowas überlegt man sich in 5 Sekunden selber wenn man's braucht. > Peinlich, das überhaupt zu erwähnen... Tja, wenn man den Compilern das auch immer an passender Stelle einfallen würde. Tut es aber nicht!!! Und diesen Sachverhalt zu erwähnen, ist mir kein bissel peinlich... Du schuldest übrigens immer noch ein funktionierende und portable C-Umsetzung... Nur diese könnte beweisen, das eine C-only-Implementierung mindestens so gut ist wie eine Implementierung durch einen fähigen Asm-Programmierer. Kannst du nicht liefern. Weil ich natürlich die Projekte so angelegt habe, dass sie wirklich alles aus der verfügbaren Hardware rausholen (rausholen müssen). Gib doch einfach zu, dass ein gelernter Asm-Programmierer bei jedem nichttrivialen Programm immer noch mindestens ein wenig besser sein kann als ein Compiler. Das tut doch nicht weh'. Schließlich ist es die objektive Wahrheit. Und ich bin absolut sicher, dass sie auch dir nur zu bewusst ist... Paßt nur nicht zu deiner Bibel und deinen Bemühungen als Shepard... Wobei mich eigentlich genau diese quasi-religiöse Grundeinstellung der C-Only-Apologeten überhaupt nur dazu bewogen hat, zu zeigen, dass sie mit vielen Aussagen schlicht und einfach LÜGEN. Eien davon ist halt die: der Compiler wird's schon richten. Nein, tut er ganz offensichtlich nicht.
Hugo H. schrieb: > Genau genommen - eines. Das Andere kann man sich aus den Hex-Files / den > .NET-Files decompilieren oder das veröffentlichte Decompilat (eines > AVR-Hex-Files) als "Veröffentlichung" studieren :-). > > Habe ich etwas übersehen? Ja. Das hätte anders laufen können, wenn da nicht der Ossifant und seine Mit-C-Hater-Hater ihre dumme nixwissende Fresse aufgerissen hätten... Übrigens tut der Absenz des Quelltextes nicht wirklich was zur Sache, wenn ein Projekt als SingleUse-Projekt angelegt ist und schlicht in dieser Anwendung funktioniert... Der Code kann genau nur das, was er können muss, er ist in keiner Form darauf vorbereitet mehr oder irgendwas anderes zu können. Genau genommen ist das Projekt sogar nur deswegen funktionsfähig, weil der Code so sehr auf das einzige Ziel des Projektes hin optimiert wurde. Das steht aber eingentlich alles schon in dem Projekt-Thread. Manche Leute begreifen es aber scheinbar erst bei der dritten Wiederholung...
c-hater schrieb: > Das steht aber eingentlich alles schon in dem Projekt-Thread. Manche > Leute begreifen es aber scheinbar erst bei der dritten Wiederholung... Manche Leute labern von "Veröffentlichung" - belassen es aber beim Labern. Dann prahle doch einfach nicht mit etwas, was nicht real ist. Deine "Angriffe" kannst Du Dir sparen :-) - die kennt hier jeder. Das Zitat ist ja irgendwie passend :-) : c-hater schrieb: > zu zeigen, dass sie > mit vielen Aussagen schlicht und einfach LÜGEN.
:
Bearbeitet durch User
So, jetzt ist's gut...wenn ich konkrete Fragen habe, mache ich einen neuen Faden auf... Gruß Rainer
Hugo H. schrieb: > Manche Leute labern von "Veröffentlichung" Tja. Es ist eine offensichtlich funktionierende Lösung veröffentlich worden. Sogar mit reichlich Zubehör, um sie mit geringem Aufwand an persönliche Wünsche anpassen zu können, solange die Fähigkeiten der Lösung dadurch nicht überschritten werden. Wo genau kann man übrigens eigentlich deine Veröffentlichungen finden?
c-hater schrieb: > Wo genau kann man übrigens eigentlich deine Veröffentlichungen finden? Nirgendwo - ich brüste mich aber auch nicht mit Pseudo-"Veröffentlichungen" von Lösungen :-)
:
Bearbeitet durch User
c-hater schrieb: > Du schuldest übrigens immer noch ein funktionierende und portable > C-Umsetzung... Ich schulde dir rein garnix. Warum sollte ich irgendeines deiner Projekte neu schreiben? > Nur diese könnte beweisen, das eine C-only-Implementierung mindestens so > gut ist wie eine Implementierung durch einen fähigen Asm-Programmierer. Du hast immer noch nicht verstanden, was ich schreibe.
Johann L. schrieb: > Du hast immer noch nicht verstanden, was ich schreibe. Was schreibst du denn deiner Meinung nach? Gibt es ein Konzept dahinter, was ich nicht verstanden habe und auf das ich antworten sollte? Was die (Nicht-)Fakten betrifft, die aus deinen Äußerungen zu entnehmen waren, habe ich wohl passend geantwortet. So ist das halt mit den bösen Fakten, die können einem gefallen oder auch nicht... Wenn sie aber offensichtlich mit der eigenen Meinung kollidieren, sollte man vielleicht am Ende doch mal die eigene Meinung überdenken... Jeder wissenschaftlich denkende Mensch würde das zumindest in Erwägung ziehen... Du nicht. Du bist ganz offensichtlich unverbrüchlicher Axiomat. C ist gottgegeben und der Endpunkt und der Urgrund allen Seins. So kenne ich sie, diese C-Apologeten. Ohne Trutz und Tadel, unbeirrbar und unbelehrbar bis in alle Ewigkeit... Amen... Dabei wissen sie weit überwiegend einen Scheiß. Du kannst wenigstens noch die Sprache richtig, die meisten dieser Blinden Wichser können nichtmal die wirklich...
Wie gesagt, du hast nicht verstanden, was ich schreibe. Vielleicht hat du es auch einfach nicht gelesen. Jedenfalls hab ich nichts geschrieben, von dem du da rumphantasierst.
:
Bearbeitet durch User
Johann L. schrieb: > Wie gesagt, du hast nicht verstanden, was ich schreibe. Doch, was du lesbar geschrieben hast, habe ich sehr wohl verstanden und adäquat kommentiert. Dein Problem ist scheinbar, dass du irgendwie glaubst, mehr geschrieben zu haben, als du tatsächlich geschrieben hast. Und wohl irgendwie auf die Kommentierung dessen wartest, was nicht da steht... Tja, Kommunikation ist irgendwie deutlich einfacher, wenn man alles schreibt, was man zu sagen hat...
c-hater schrieb: > Tja, Kommunikation ist irgendwie deutlich einfacher, wenn man alles > schreibt, was man zu sagen hat... Ergänzend: Wenn deine Behinderung so weit reicht, dass du kein deutsch mehr kannst, darfst du es auch ein C schreiben. Ich werde es trotzdem verstehen... Nur wenn garnix substantielles da steht, dann muß auch ich passen...
Rainer V. schrieb: > Und nun verstehe ich die Doc's (auch > hier im ".net") nicht. Bin jetzt nur zufaellig auf diesen Thread gestossen.Ich nehme an,dass du mittlerweile bei all den Postings hier schon zum Profi mutiert bist,aber vielleicht interessiert es den einen oder anderen Newbie wie Interrupts verarbeitet werden. Es ist zwar eine Arduinoabhandlung aber die basieren ja auf Atmel uCs... Angehaengte Pdf anschauen und fuer gut befinden oder bei Nichtgefallen einfach loeschen...
c-hater schrieb: > Du schuldest übrigens immer noch ein funktionierende und portable > C-Umsetzung... > > Nur diese könnte beweisen, das eine C-only-Implementierung mindestens so > gut ist wie eine Implementierung durch einen fähigen Asm-Programmierer. Das hatten wir schon vor Jahren. Damals behauptete Moby, seine Assembler-Programme wären mittels C bezgl. Größe, Funktionalität und Geschwindigkeit nicht zu schlagen. Die ganze Diskussion mündete dann in eine Challenge, wo Yalu schlussendlich Mobys Assembler-Programm in C neu implementierte. Dieses hatte lediglich 158 Bytes Binärcode und schlug Mobys Assemblerprogramm von 206 Bytes um Längen. RAM-Verbrauch war derselbe, nämlich 2 Bytes. Nachzulesen hier: Beitrag "Re: Assembler wieder auf dem Weg nach vorn" P.S. Moby hielt sich auch für den Assembler-Weltmeister, musste aber nach über 2000 Thread-Beiträgen eines besseren belehrt werden. Von daher wäre ich an Deiner Stelle mit solchen Aussagen ganz ganz vorsichtig.
Frank M. schrieb: > Die ganze Diskussion mündete dann in eine Challenge, wo Yalu > schlussendlich Mobys Assembler-Programm in C neu implementierte. Dieses > hatte lediglich 158 Bytes Binärcode und schlug Mobys Assemblerprogramm > von 206 Bytes um Längen. RAM-Verbrauch war derselbe, nämlich 2 Bytes Na ja, mit allen Tricks - z. B.: // Hilfsmakros #define REG(regno) __asm__(#regno) #define NAKED_IN_SECTION(sect) __attribute__((naked, section(sect))) // GLobale Registervariablen register uint8_t zero REG( 1); // GCC erwartet in R1 immer eine 0 register conv16 adcsum REG( 2); // Summe von jeweils 8 ADC-Werten register uint8_t chksum REG( 4); // Pr³fsumme register conv24 output REG(14); // 24-Bit-Ausgabe register uint8_t cycle REG(17); // Zõhler der 5ms-Zyklen Welcher "normale" C-Programmierer kümmert sich darum? Ich mag C-Hater nicht besonders (Moby kenne ich nicht) aber dann kann ich auch in Assembler (mit Makros) programmieren.
:
Bearbeitet durch User
c-hater schrieb: * Ich bat dich, nicht immer wieder falsche Sachstände bzgl. avr-gcc / avr-g++ zu repetieren, die seit bereits 3 Compilerversionen und > 3 Jahren behoben sind (konkret PR81268). * Du antwortest darauf mit der Aufforderung, ich solle eines der Projekte aus deiner Asm Mottenkiste nachimplementieren, und behauptest ich schulde dir was. Johann L. schrieb: > >> Falls du dich auf avr-gcc beziehst, das ist schon seit bereits 3 >> Compiler-Versionen nicht mehr so. Soviel zu "Lernen". > > Ah ja. Deann setze enfach eines der beiden von mir veröffentlichen > Anwendungen (zu finden in Projekte & Code) in C um, meinetwegen auch im > topaktuellen avr-gcc. Es wird dir nicht gelingen. > > Erst, falls das doch der Fall wäre, gäbe es für mich etwas zu lernen... Von dem kiloweise Weihrauch, den du dir täglich zur Selbstbeweihräucherung reinziehst, sind deine Hirnwindungen dermaßen verharzt, dass du garantiert nix mehr lernst. Schon garnicht Textverständnis. Oder eine Diskussion in der Sache zu führen — die übrigens in diesem Thread wie in 99.9% aller anderen Threads komplett Offtopic ist. Von daher: Noch viel Spaß mit deinen Hasstiraden und den Stimmen in deinem Kopf, die wer weiß was für Implikationen und lächerliche Forderungen erfinden, nur um irgendwie zu deiner Mottenkiste zu führen um allen zeigen zu können, was für ein Toller Asm-Hecht du bist und in Aspekten besser abschneidest, als ein bestimmtes Computerprogramm.
Johann L. schrieb: > * Ich bat dich, nicht immer wieder falsche Sachstände bzgl. avr-gcc / > avr-g++ zu repetieren, die seit bereits 3 Compilerversionen und > 3 > Jahren behoben sind (konkret PR81268). Naja, wenn das alles so schick ist, sollte es ja kein Problem sein, den Westminster in C umzusetzen. Ich habe es jedenfalls nicht geschafft, ohne massive Ausflüchte nach Asm und in nichtportable Compilerfeatures unternehmen zu müssen. D.h.: es ist viel, viel effizienter, das gleich in Assembler umzusetzen. Genau das habe ich getan. Aber du könntest an diesem Beispiel doch echt mal die gnadenlose Überlegenheit von C und deinen überragenden Fähigkeiten als C-Programmierer gucken lassen. Indem du es hinreichend schnell und hinreichend klein für einen Tiny85, dabei aber trotzdem portabel umsetzt. Das wäre dann doch mal ein echter Hingucker... Aber in einem Punkt hast du Recht: ein echte Schuld, das zu tun, besteht natürlich nicht. Wäre mehr so als eine Art Ehrenschuld anzusehen...
c-hater schrieb: > Aber du könntest an diesem Beispiel doch echt mal die gnadenlose > Überlegenheit von C und deinen überragenden Fähigkeiten als > C-Programmierer gucken lassen. Drehen wir den Spieß doch mal um. IRMP läuft mit ein- und demselben Quellcode auf vielen ATTinys, ATMegas, PICs, STM32, STM8, TI Stellaris, ESP8266, TEENSY MK20DX256VLH7, MBED LPC1347, MBED LPC4088 und anderen µCs. Programmiere den mal in ASM nach. Dafür müsstest Du für jeden µC ein eigenes Assembler-Programm schreiben, eine absolut sinnlose Arbeit.
Hugo H. schrieb: > Na ja, mit allen Tricks - z. B.: > > // Hilfsmakros > #define REG(regno) __asm__(#regno) > ... > aber dann kann ich auch in Assembler (mit Makros) programmieren. Yalu hat lediglich einige Variablen in Register gelegt, um RAM zu sparen, damit er nicht mehr als 2 Byte im RAM benötigt. Das war die Vorgabe von Moby. Trotzdem ist es ein C-Programm. Da ist keine einzige Zeile Assembler-Code, lediglich einige Bindungen an CPU-Register.
Frank M. schrieb: > Programmiere den mal in ASM nach. Dafür müsstest Du für jeden µC ein > eigenes Assembler-Programm schreiben, eine absolut sinnlose Arbeit. Der gemeine Assembler Fetischist hat an solchen Argumenten kein Interesse und blendet sie geflissentlich aus. Es wird dir erklärt werden, dass auch C/C++ nicht vollständig Plattformneutral sind.
Arduino Fanboy D. schrieb: > Es wird dir erklärt > werden, dass auch C/C++ nicht vollständig Plattformneutral sind. Was halt humbug ist, weil ich in ASM nicht eine einzige Zeile Plattformneutral programmieren kann. In C kann ich große Teile völlig unabhängig von der Hardware programmieren. Wenn man es halt tut. Der gemeine ASM Programmierer würde wohl an jeder beliebigen Stelle direkte Registerzugriffe auf die HW einbauen.
Frank M. schrieb: > Da ist keine einzige Zeile > Assembler-Code https://de.wikipedia.org/wiki/Integrierter_Assembler https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html Frank M. schrieb: > __asm__(#regno) Vielleicht sehe ich das falsch, aber in C habe ich "normalerweise" keinen direkten Zugriff auf Register. Klar, wenn man sich Prolog und Epilog einer ISR sparen will, in welcher Werte verändert werden, dann muss man sich etwas einfallen lassen ... Haarspalterei meinetwegen, aber "ganz sauber" ist das nicht.
Beitrag #6415584 wurde von einem Moderator gelöscht.
Hugo H. schrieb: > https://de.wikipedia.org/wiki/Integrierter_Assembler > https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html Ich schrieb bewusst "Assembler-Code". Mit Code meine ich Opcode. Und da ist kein einziger Opcode im C-Code. Dass man __asm__(#regno) schreiben muss, um eine Variable einem Register zuzuordnen, heisst nicht unbedingt, dass da nun Assembler-Code folgt. Hugo H. schrieb: > Vielleicht sehe ich das falsch, aber in C habe ich "normalerweise" > keinen direkten Zugriff auf Register. Normalerweise nicht, bei direkter µC-Programmierung sehe ich das als legitim an, schließlich gibt es ja dieses Instrument. Nur so kann man auch ein Mini-Progrämmchen in ASM fair mit C vergleichen, weil Moby tatsächlich eben auch fast alles in Registern gehalten hat - eben weil es nur ein Mini-Progrämmchen war. Hätte es sich um ein wesentlich umfangreicheres Programm gehandelt, hätte Moby seine Variablen auch im RAM auslagern müssen. Dann hätte Yalu natürlich auch darauf verzichtet. Denn dann kann der C-Compiler seine Stärken auch wesentlich besser ausspielen: er hat ab einer bestimmten Programmgröße allemal ein viel besseres "Gedächtnis" über die aktuell verwendeten Register als ein Mensch.
:
Bearbeitet durch Moderator
Hugo H. schrieb: > Frank M. schrieb: >> Da ist keine einzige Zeile Assembler-Code > > https://de.wikipedia.org/wiki/Integrierter_Assembler > https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html > > Frank M. schrieb: >> __asm__(#regno) > > Vielleicht sehe ich das falsch, aber in C habe ich "normalerweise" > keinen direkten Zugriff auf Register. Der Code ist kein C, sondern GNU-C: __asm kennzeichnet nicht nur inline Assembly, sondern auch lokale und globale Registervariablen. Letztere verwendet Yalu in seinem Code, wie leicht and Yalus Quellkommentaren und dem Code selbst zu erkennen ist. > Klar, wenn man sich Prolog und Epilog einer ISR sparen will, > in welcher Werte verändert werden, dann muss man sich etwas > einfallen lassen... Die einzige Möglichkeit, Register, die in einer ISR verwendet werden, nicht im ISR-Prolog sichern zu müssen, sind globale Register. Ob dies im Beispiel dem Laufzeit-Overhead der ISR geschuldet war, dem RAM-Verbrauch, oder ob es nur eine von Moby aufgestellte Bedingung war, welche man propremlos hätte fallen lassen können, weiß ich jetzt nicht.
:
Bearbeitet durch User
Beitrag #6415726 wurde von einem Moderator gelöscht.
Frank M. schrieb: > Dass man __asm__(#regno) > schreiben muss, um eine Variable einem Register zuzuordnen, heisst nicht > unbedingt, dass da nun Assembler-Code folgt. Entschuldige bitte - aber für mich ist das Unsinn. Wenn ich Register unter einem definierten Namen reserviere greife ich direkt in die Assembler-Generierung (Compilierung) ein. Ich schränke den C-Compiler in der Verwendung der Register ein und beeinflusse das Compilat und damit auch das Assembler-Zwischenprodukt.
Hugo H. schrieb: > ch schränke den C-Compiler in der Verwendung der Register ein und > beeinflusse das Compilat und damit auch das Assembler-Zwischenprodukt. Stimmt sicher. Und obwohl der Compiler damit eingeschränkte Möglichkeiten hatte, war das Ergebnis von Yalu kürzer damals.
900ss D. schrieb: > Und obwohl der Compiler damit eingeschränkte > Möglichkeiten hatte, war das Ergebnis von Yalu kürzer damals. Nicht obwohl - sondern weil.
Hi Mal wieder ein wahnsinnig langer Thread, der eigentlich schon nach 15 Beiträgen hätte sein Ende finden können, nur weil mal wieder ein Glaubenskrieg über die Programmiersprache ausgebrochen ist. Man Leute, es ist doch Sch...egal, wer welche Sprache benutzt oder bevorzugt. Beruflich werden die meisten C nehmen, ganz selten Assembler, aber wer in seiner kleinen Kammer bastelt, der darf sich auch mit Assembler masochieren. Tu ich auch, weil ich C für mich nie benötigt habe. Sollte das in den letzten 30 Jahren meines Lebens nochh notwendig sein, nun, dann tu ich mir diese Stottersprache an, aber nicht, weil einer von euch mich überzeugt, sondern weil es erforderlich ist. Aber, das heißt nicht automatisch, das die C -Programmierer gefälligst Assembler lernen oder anwenden müssen. Bei denen, die programmieren zum Beruf haben, setze ich sowieso voraus, das sie zu 80 % auch Assembler können. Was bleibt, sind die kleinen starrköpfigen Glaubenskrieger, deren Anpassungsfähigkeit einem Betonpfeiler gleicht. Ausgang war mal die Frage zu Interrupts eines AVR. Erinnert ihr euch noch? Gruß oldmax
Martin V. schrieb: > Ausgang war mal die Frage zu Interrupts eines AVR. Erinnert ihr euch > noch? > Gruß oldmax Kennst Du das berühmte Zitat von Dieter Nuhr (analog einige Zeit davor von "Alfred Tetzlaff") ?
Beitrag #6415907 wurde von einem Moderator gelöscht.
Beitrag #6416057 wurde von einem Moderator gelöscht.
Beitrag #6416064 wurde von einem Moderator gelöscht.
Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.