Hallo, ich habe schon länger (13 Jahre) nichts mehr mit Mikrocontrollern gemacht, und nun steht der Winter vor der Tür. Da will ich mal langsam wieder was machen (irgendeine Vernetzung mit Temperatur- und Feuchtefühlern, 2 Fensterkontakte usw.). Ich habe mir von "damals" gemerkt, daß eine ISR so kurz wie nur irgend möglich sein soll und in der mainloop ein Flag zur Verarbeitung gesetzt weren sollte. Da jetzt auch etwas batteriebetriebenes ansteht, soll die Laufzeit so kurz wie möglich sein, um den Akku zu schonen. Also sleep mit Interruptbetrieb. Ist es heute noch genauso? Ich fand es schon immer übersichtlicher, alles an einem Ort (in diesem Fall in der ISR) zu haben. Und die heutigen Controller (der Chinamann steckt mir so ein Bluepill-Board doch glatt für unter 2 € in den Briefkasten; sagenhaft!) haben auch frei priorisierbare Interrupts. Mehr als arbeiten kann das Ding im schlimmsten Fall ja nicht. Klar ist das extrem von der Anwendung abhängig. Also vernünftiges Konzept mit ISR-Prioritäten und fertig? Klar muß man gewisse Abläufe vor Unterbrechung schützen. Aber gibt es diese "Regel" bei modernen Controllern noch?
das hat nix mit modern zu tun. Ein Interrupt kann ja durchaus öfter vorkommen und wenn da der vorige Interrupt nicht mit seiner Aufgabe fertig ist kommts, nach wie vor, zu Problemen. Die Aussage hat also nix an Aktualität verloren.
Im Detail mag sich in den letzten 13 Jahren einiges geändert haben. Aber die Prinzipien sind seit über 30 Jahren unverändert.
Prinzipiell finde ich es immer eine gute Idee, den Programmfluss so straightforward zu machen, wie es geht und Interrupts dafür zu nutzen, wofür sie gedacht sind, nämlich asynchrone Ereignisse zu bearbeiten. Wenn du dich auf die Prioritäten der Interrupts verlässt, bekommst du eine beliebig verschachtelte Ausführung von Tasks, die sich nur sehr schwer vorraussehen lässt. Das erhöht die Komplexität des ganzen Programmes. Ich bevorzuge bei meinen µC Programmen eine Hauptschleife, die möglichst schnell durchläuft und die Subtasks so aufteilt, dass sie auch schnell und in vorhersehbarer Zeit und Reihenfolge ablaufen. Das begünstigt auch die Reaktionszeit, z.B. für externe Kommunikation. Die Interrupts sind so kurz gehalten, dass sie zu jedem Zeitpunkt abgearbeitet werden können und die Abarbeitung des Hauptprogrammes nicht wesentlich verlängern. Wie viel das sein darf, hängt natürlich von der Anwendung, dem µC und den zeitlichen Erfordernissen ab. Also zusammengefasst: Ja, diese Regel zu befolgen ist eine gute Idee. Ausnahmen bestätigen die Regel.
Diese Faustregeln haben Gründe, denn eine ISR blockiert während ihrer Ausführung jegliche andere Prozessoraktivität (inklusive anderer Interrupts, wobei Priorisierung helfen kann). Langsame ISRs können also dazu führen, dass auf Ereignisse manchmal erst verzögert reagiert werden kann (Jitter), oder dass Interrupts verloren gehen. Das gilt für alle Controller, egal ob neu oder alt. Wenn dein System keine wirklich harten Echtzeitanforderungen hat und du deine Aktionen zügig innerhalb der ISR erledigen kannst, dann tue das auch. Beispiel: Es ist normalerweise kein Problem, in der ISR des UARTs das Zeichen auszulesen, durch einen kleinen Automaten (z.B. wegen Framing, Escaping, ...) zu schicken, das Ergebnis in einen Ringpuffer zu schreiben und die Mainloop zu informieren. Die Verarbeitung des Ganzen (Parsen, Protokoll implementieren, Antworten) ist dagegen vergleichsweise aufwändig und gehört ins Hauptprogramm. Das ist auch wichtig, weil diese Funktionen möglicherweise nicht reentrant sind, also nicht immer zuverlässig aus einer ISR aufgerufen werden können.
Na ja, bei der Anwendung die der TO vor hat, da wartet das Hauptprogramm ja förmlich auf den Interrupt. Dann kann man da auch in der ISR was abarbeiten. Ich habe für meinen Mercedes (190ger) einen Tester gebaut, der die Fehler verzögert wieder gibt und immer wiederholt. Im Grunde wartet das ganze Programm doch nur auf den Interrupt, um dann das eingelesene zu wiederholen, bis ich nachgesehen habe, was das für ein Fehler ist. Irgendwann wollte ich einmal daraus ein richtigen Tester bauen ... wollte. Aber da der Benz so gut läuft, brauche ich nicht mal den Tester; hoffentlich nicht. :-)
F. F. schrieb: > Na ja, bei der Anwendung die der TO vor hat, da wartet das Hauptprogramm > ja förmlich auf den Interrupt. Dann kann man da auch in der ISR was > abarbeiten. Wer sagt, dass das Hauptprogramm nur auf den Interrupt wartet. Könnte es nicht sein, dass im Hauptprogramm auch noch diverse andere Dinge ablaufen, die nicht ganz zeitkritisch sind, aber doch Probleme bekommen, wenn jemand im Interrupt auf die Idee kommt, bspw. auf das Loslassen einer Taste o.ä. zu warten?
Wolfgang schrieb: > Wer sagt, dass das Hauptprogramm nur auf den Interrupt wartet. Niemand, das habe ich aus seinem Vorhaben interpretiert. Da er doch wieder anfängt, wird es sicher eher um Temperatur messen und anzeigen handeln, so vermute ich das hier einfach. Aber weiter oben steht es auch schon. Grundsätzlich schnell rein und schnell raus aus der ISR, wenn es nicht zeitkritisch ist oder werden kann, auch mal in der ISR abarbeiten.
S. R. schrieb: > Diese Faustregeln haben Gründe Genau nur zwei: 1) Inkompetenz der Hochsprachen-Programmierer 2) Insuffizienz und Ineffizienz der Hochsprachen Wenn man also die Hochsprache verläßt, gelten alle angeführten Gründe einfach nicht mehr. Als da wären: Frank L. (hermastersvoice): > Ein Interrupt kann ja durchaus öfter > vorkommen und wenn da der vorige Interrupt nicht mit seiner Aufgabe > fertig ist kommts, nach wie vor, zu Problemen Fällt aus wegen: - wenn in Assembler programmiert, ist zumindest die maximale (oft auch die mittlere) Laufzeit JEDER ISR eine wohlbekannte Größe. - Wenn die maximalen Interruptraten ebenfalls bekannt ist (beim AVR z.B. trifft das auf die weit überwiegende Mehrheit der möglichen Interruptquellen zu, Ausnahmen sind nur PCINT, INT und ICP), genügt das (in Kombination mit dem Wissen um die Laufzeit der ISRs) bereits alleine, um abzusichern, dass die Applikation niemals die Echtzeit verläßt. - Für die verbleibenden "unsicheren" Interruptquellen kann man leicht erzwingen, dass die Interruptrate immer unterhalb dessen bleibt, was das System aktuell verarbeiten kann, indem man schlicht die lokalen IRQ-Flags dieser Interruptquellen benutzt. Dafür gibt es die nämlich... S. R. (svenska): > denn eine ISR blockiert während ihrer > Ausführung jegliche andere Prozessoraktivität Fällt aus wegen: - man kann in Assembler leicht (nach Abarbeitung zwingend exklusiv abzuarbeitender Codeteile) die Interrupts global wieder aktivieren und erhält damit eine Art hoch priorisiertem, aber durch nachfolgende IRQs unterbrechbarem Task für den Rest der ISR. S. R. (svenska): > Langsame ISRs können also dazu führen, dass auf Ereignisse manchmal erst > verzögert reagiert werden kann (Jitter), oder dass Interrupts verloren > gehen. Das gilt für alle Controller, egal ob neu oder alt. Ja. Es gilt vor allem auch vollkommen unabhängig davon, wie die Arbeitsteilung zwischen ISR (exklusiv), ISR(als hochpriorisiertem, unterbrechbaren Task) und main geregelt ist. Wenn die Rechenzeit schlicht nicht reicht, ist immer Ende Gelände. Genau deswegen ist es so wichtig, jederzeit absolut sicher sein zu können, dass die Rechenzeit unter allen Umständen reicht und die volle Kontrolle darüber zu haben, wie die Rechenzeit für die gegebene Gesamtaufgabe am sinnvollsten zu verteilen ist. Und das geht eben nur, wenn man den Rechenzeitbedarf exakt kennt und die verfügbare Rechenzeit möglichst sinnvoll verteilen kann. -> Assembler rules. MikeH (Gast): > Das erhöht die Komplexität des ganzen Programmes. Das ist leider vollkommen unbezweifelbar wahr, genau hier greift das Thema "Programmierer-Kompetenz". Allerdings: nur so ist das Optimum zu erreichen. Und, neben Anwendungen, die den Controller bezüglich seiner Leistungsfähigkeit ausreizen, ist es gerade auch für batteriebetriebene Anwendungen wichtig, dieses Optimum zu erreichen. Denn nur das stellt eben auch gleichzeitig das Optimum für minimalen Batterieverbrauch dar... Und, als logische Folge dieses Sachverhaltes: Man erkennt dieses Optimum es in erster Näherung daran, dass in der Hauptschleife in main rein garnix passiert, außer dem Befehl zum Einschlafen. Warum ist das so? Natürlich: weil erst dann zumindest alle unnötig aufgewandte Rechenzeit für Polling eleminiert ist... Und was ist wiederum die logisch Folge? Natürlich: alle Funktionalität muss in ISRs stattfinden. Tja, die formale Logik ist schon eine schöne Sache, um Konzepte bezüglich ihrer Sinnhaftigkeit zu durchleuchten...
Restarter schrieb: > daß eine ISR so kurz wie nur irgend möglich sein soll und in > der mainloop ein Flag zur Verarbeitung gesetzt weren sollte. Wenn in der ISR tatsächlich nur ein Flag gesetzt wird, kannst du auch komplett auf die ISR verzichten und direkt das Hardwareflag aus der Hauptschleife heraus abfragen und rücksetzen. Was in der ISR verarbeitet werden soll/muss und was außerhalb verarbeitet werden kann, kann man pauschal nicht sagen. Das kommt auf den Einzelfall an. Was man aber in einer ISR in den meisten Fällen vermeiden sollte ist, auf Ereignisse in Schleifen zu warten, oder gar Warteschleifen (_delay_xx()) zu verwenden. Auch da kann es Ausnahmen geben, wenn die Ereignisse z.B. verhältnismäßig schnell eintreten, oder die Wartezeit kurz ist.
c-hater schrieb: > Genau nur zwei: > > 1) Inkompetenz der Hochsprachen-Programmierer > 2) Insuffizienz und Ineffizienz der Hochsprachen Warum meinst du eigentlich, Hochsprachenprogrammierer und insbesondere C-Programmierer, ständig zu Idioten erklären zu müssen? Was danach kommt ist doch völlig in Ordnung. Das liest nur keiner mehr, weil er bei den ersten Sätzen schon die Schnauze voll hat von deiner blöden Anmache. Meine Güte, hast du das wirklich so nötig? Warum versuchst du nicht einfach mal, nur mit Kompetenz zu überzeugen, anstatt mit dieser Prollerei?
:
Bearbeitet durch User
c-hater schrieb: > Natürlich: weil erst dann zumindest alle unnötig aufgewandte Rechenzeit > für Polling eleminiert ist... > Und was ist wiederum die logisch Folge? Natürlich: alle Funktionalität > muss in ISRs stattfinden. Wenn ein Teil der Abarbeitung in der Hauptschleife stattfindet, dann heißt das noch lange nicht, dass ein Polling stattfindet. Die Hauptschleife kann nach Interrupt und einem Durchlauf wieder zu Bett gehen.
Thomas E. schrieb: > Warum meinst du eigentlich, Hochsprachenprogrammierer und insbesondere > C-Programmierer, ständig zu Idioten erklären zu müssen? Nomen es Omen. Hass will raus.
c-hater schrieb: > Fällt aus wegen: > - wenn in Assembler programmiert, ist zumindest die maximale (oft auch > die > mittlere) Laufzeit JEDER ISR eine wohlbekannte Größe. Die maximale Laufzeit einer ISR ist in asm wie in C immer "unendlich" - für nicht-triviale Varianten ist das für einen Compiler nicht erkennbar, und für den Programmierer auch nicht notwendigerweise. Die "Bekanntheit" der "mittleren" Laufzeit, was immer das sein soll, ist auch nicht davon abhängig ob in die Routine in C, Forth, ASM oder sonstwas programmiert ist. Alles imperativ, und wird mehr oder weniger 1:1 in Maschinenkode umgesetzt. Ich halts mit ISRs so: das was man sofort erledigen kann und O(1) ist gleich machen, den Rest delegieren. In der Hauptschleife schlafen und nach einem Aufweck-Event nachschaun was es zu tun gibt und ggf. abarbeiten bevor man sich wieder hinlegt.
Ein Nachteil bei umfangreichen ISR ist, daß sie nicht immer gleich viel freien Stack vorfinden. Denn es kommt darauf an, wann genau sie aufgerufen werden. Bei µC mit wenig RAM (<2kB) kann das schnell ein Knackpunkt sein.
Stefan U. schrieb: > Ein Nachteil bei umfangreichen ISR ist, daß sie nicht immer gleich viel > freien Stack vorfinden. Denn es kommt darauf an, wann genau sie > aufgerufen werden. Bei µC mit wenig RAM (<2kB) kann das schnell ein > Knackpunkt sein. Ein anderes Problem bei umfangreichen ISR und Verschachtelung selbiger ist, dass man nur reentrante Funktionen aufrufen darf. Sobald da irgendwas einen Seiteneffekt hat gehts potentiell in die Hose. Ganz abgesehen von den Problemen die man sich einhandelt, wenn zwei ungleich priorisierte ISRs auf die selbe Datenstruktur nicht-lesend zugreifen müssen.
Thomas E. schrieb: > Warum meinst du eigentlich, Hochsprachenprogrammierer und insbesondere > C-Programmierer, ständig zu Idioten erklären zu müssen? Weil die seit 40 Jahren genau das mit Assembler-Programmierern tun... Am meisten gehen mir allerdings die zielgerichtet an Anfänger (die es ja schließlich noch nicht besser wissen können) gerichteten offensichtlichen Lügen auf den Keks, als da z.B. wären: -in C braucht man nix mehr über das System zu wissen, Compiler und Libs richten das schon. -C löst alle deine Probleme -C ist einfach zu lernen -C ist portabel und gleichzeitig(!) hocheffizient Wenn das alles endlich aufhört, höre ich auch auf. So einfach ist das eigentlich...
Michael B. schrieb: > Wenn ein Teil der Abarbeitung in der Hauptschleife stattfindet, dann > heißt das noch lange nicht, dass ein Polling stattfindet. Na die Lösung, die das realisiert, möchte ich doch gern einmal sehen... Ich gehe allerdings nicht davon aus, dass du sie liefern kannst. Falls doch: der Nobelpreis ist dir sicher. Ich selber würde dich dafür vorschlagen.
c-hater schrieb: > -in C braucht man nix mehr über das System zu wissen, Compiler und Libs > richten das schon. Niemand behauptet das. > -C löst alle deine Probleme Niemand behauptet das. > -C ist einfach zu lernen Nur Leute, die kein C können, behauptet das. > -C ist portabel und gleichzeitig(!) hocheffizient In vielen Situationen ist das praktisch auch so. Kommt darauf an, wie man "hocheffizient" definiert. Wenn ein C-Programm all das tut was es soll, gibt es keinen Grund es in ASM zu schreiben. D.h. es ist hocheffizient.
rmu schrieb: > Die maximale Laufzeit einer ISR ist in asm wie in C immer "unendlich" - Kompletter Bullshit. Wo hast du denn das aufgeschnappt? > Die "Bekanntheit" der "mittleren" Laufzeit, was immer das sein soll, ist > auch nicht davon abhängig ob in die Routine in C, Forth, ASM oder > sonstwas programmiert ist Doch, natürlich. Es setzt nur folgendes voraus: 1) die Laufzeiten aller ISR-Verzweigungen zu ermitteln. 2) Die Interruptrate für jeden dieser Zweige zu ermitteln. Die erste Forderung ist in Assembler leicht realisierbar, die zweite Forderung oft (aber leider längst nicht immer) zumindest bei regelmäßig aufgerufenen Interrupts. Ist aber nicht so schlimm, in einem solchen Fall nimmt man halt die maximale Laufzeit als mittlere Laufzeit an und ist damit IMMER auf der Sicheren Seite.
Kann man es eigentlich auch als Interrupt betrachten, wenn c-hater in eine harmlose Diskussion reingrätscht und forthin nur noch über C vs ASM diskutiert wird? Oder ist das bald eine Totschleife? Oder beides?
:
Bearbeitet durch User
c-hater schrieb: >> Die maximale Laufzeit einer ISR ist in asm wie in C immer "unendlich" - > Kompletter Bullshit. Wo hast du denn das aufgeschnappt? https://de.wikipedia.org/wiki/Halteproblem
A. K. schrieb: > Kann man es eigentlich auch als Interrupt betrachten, wenn c-hater in > eine harmlose Diskussion reingrätscht und forthin nur noch über C vs ASM > diskutiert wird? Solch ein haltloses Unterfangen, wie c-hater es betreibt, ist Teil des Halteproblems. Das heißt ein Thread, in dem er auftaucht, wird endlos.
c-nicht-hater schrieb: > Niemand behauptet das. Wieviele Tausende Beiträge soll ich dir alleine aus diesem Forum extrahieren, die das Gegenteil beweisen? Jaja: "niemand" hat die Absicht, eine Mauer zu bauen...
c-hater schrieb: >> Die "Bekanntheit" der "mittleren" Laufzeit, was immer das sein soll, ist >> auch nicht davon abhängig ob in die Routine in C, Forth, ASM oder >> sonstwas programmiert ist > > Doch, natürlich. Es setzt nur folgendes voraus: > > 1) die Laufzeiten aller ISR-Verzweigungen zu ermitteln. > 2) Die Interruptrate für jeden dieser Zweige zu ermitteln. > > Die erste Forderung ist in Assembler leicht realisierbar, die zweite > Forderung oft (aber leider längst nicht immer) zumindest bei regelmäßig > aufgerufenen Interrupts. Ist aber nicht so schlimm, in einem solchen > Fall nimmt man halt die maximale Laufzeit als mittlere Laufzeit an und > ist damit IMMER auf der Sicheren Seite. Warum ist die erste Forderung bei Assembler leicht realisierbar? Was spräche dann dagegen, sich die übersetzte Hochsprache vorm assemblieren anzusehen? Das ist genauso "Assembler", eventuell mit ein bissl mehr Struktur als manuell erstellt. Selbst wenn man 1 und 2 erledigt hat kann man deswegen noch lange nicht "einfach" abschätzen ob die ISR nicht doch irgendwo versteckt eine Endlosschleife enthält oder sonstige Probleme Fehler Deadlocks wasauchimmer. Siehe Halteproblem.
rmu schrieb: > Warum ist die erste Forderung bei Assembler leicht realisierbar? Naja, leicht zumindest bei Systemen wie dem AVR8... Allerdings ist es ja gerade bei solchen leistungsschwachen System eben auch besonders oft nötig, maximale Effizienz zu erreichen. > Was > spräche dann dagegen, sich die übersetzte Hochsprache vorm assemblieren > anzusehen? Die simple (und sicherlich auch dir bekannte) Tatsache, das es nach dem nächsten Compilerlauf völlig anders aussehen kann. Sei es durch abweichende Compilerflags oder abweichende Version desselben Compilers oder gar durch Verwendung eines alternativen Compilers. > Selbst wenn man 1 und 2 erledigt hat kann man deswegen noch lange nicht > "einfach" abschätzen ob die ISR nicht doch irgendwo versteckt eine > Endlosschleife enthält oder sonstige Probleme Fehler Deadlocks > wasauchimmer. Wer hat behauptet, dass fehlerhafter Code in Assembler fehlerfrei laufen würde? Niemand. Im Gegenteil habe ich explizit auf die notwendige Kompetenz des Programmierers hingewiesen... Allerdings gilt das natürlich in C und jeder anderen Hochsprache genauso. Der Unterschied ist halt: Fehlerfreiheit alleine bedeutet hier mit an Sicherheit grenzender Wahrscheinlichkeit (zumindest bei ISR-Nutzung) immer noch, dass man ziemlich weit weg vom Optimum ist... Und komplett ohne Assembler (in vielen Bibliotheken versteckt) sähe es nochmal sehr viel grottiger aus...
c-nicht-hater schrieb: > Wenn ein C-Programm all das tut was es soll, gibt es keinen Grund es in > ASM zu schreiben. D.h. es ist hocheffizient. Hähä, damit kommen wir endlich wieder auf das eigentliche Thema des Threads zurück... Bei batteriebetriebenen Anwendungen z.B. reicht es nämlich noch NICHT aus, dass ein Programm einfach nur unter allen Umständen fehlerfrei funktioniert (das halte ich sowieso für eine zumindest erstrebenswerte Mindestforderung, nur in Kreisen der C&P-Programmierer hat man dazu andere Meinungen), um das Prädikat "hocheffizient" zu verdienen. Nein, hier ist eben eine der primären Forderungen, dass es nebenbei auch noch die Batterie so wenig wie irgend möglich belastet. Denn hier kostet jeder Takt programmerierischen Unvermögens schlicht bares Geld. Nicht das des unfähigen Programmierers, sondern das des Anwenders...
c-hater schrieb: > rmu schrieb: > >> Warum ist die erste Forderung bei Assembler leicht realisierbar? > > Naja, leicht zumindest bei Systemen wie dem AVR8... Allerdings ist es ja > gerade bei solchen leistungsschwachen System eben auch besonders oft > nötig, maximale Effizienz zu erreichen. Also ich find das nur mühsam, man kann sich vielleicht die eine oder andere Schleife anschaun, aber mehr schon nicht. Vor allem wenn da "kreativ" programmiert wurde, je kreativer desto schwieriger nachzuvollziehen. Selbst wenn man das selber vor 10 Jahren programmiert hat. >> Was >> spräche dann dagegen, sich die übersetzte Hochsprache vorm assemblieren >> anzusehen? > > Die simple (und sicherlich auch dir bekannte) Tatsache, das es nach dem > nächsten Compilerlauf völlig anders aussehen kann. Sei es durch > abweichende Compilerflags oder abweichende Version desselben Compilers > oder gar durch Verwendung eines alternativen Compilers. Compilerflags ändert man an einem bestehenden Programm so gut wie gar nie, und selbst dann hat das meistens auf den generierten Code wenig Auswirkung, von den Flags die die Optimierung kontrollieren abgesehen. Compiler austauschen tut man auch eher selten, selbst ein update auf eine neue Version passiert nicht "von selber", eine vernünftige Konfigurations-Verwaltung inkludiert das ausserdem. Die Komplexität einer Routine ändert sich durch Compiler-Flags und -Versionen nicht. Grobe Laufzeitunterschiede kann man sich nur durch deaktivieren von inline oder andere Bibliotheken einfangen, davon abgesehen wirds im Großen und Ganzen vergleichbar sein. Siehe z.B. http://colecovision.eu/stm8/compilers.shtml >> Selbst wenn man 1 und 2 erledigt hat kann man deswegen noch lange nicht >> "einfach" abschätzen ob die ISR nicht doch irgendwo versteckt eine >> Endlosschleife enthält oder sonstige Probleme, Fehler, Deadlocks >> wasauchimmer. > > Wer hat behauptet, dass fehlerhafter Code in Assembler fehlerfrei laufen > würde? Niemand. Im Gegenteil habe ich explizit auf die notwendige > Kompetenz des Programmierers hingewiesen... > > Allerdings gilt das natürlich in C und jeder anderen Hochsprache > genauso. Die Forensoftware hat da meine Schrägstriche rund um Fehler umgewandelt. Auch fehlerfreie Routinen können ein schwer abschätzbares Laufzeitverhalten aufweisen, vor allem wenn sie (eventuell beliebige) Eingabe-Daten verarbeiten. Kann man eine Routine, die eine 32bit float oder int bekommt noch für alle Möglichkeiten simulieren / testen, geht das z.b. für 2 floats oder 2 32bit integer nicht mehr. > Der Unterschied ist halt: Fehlerfreiheit alleine bedeutet hier mit an > Sicherheit grenzender Wahrscheinlichkeit (zumindest bei ISR-Nutzung) > immer noch, dass man ziemlich weit weg vom Optimum ist... Das Optimum hängt von der Kostenfunktion ab. Üblicherweise sind Entwickler nicht gratis, Wartbarkeit und Lesbarkeit der Programme spielen in dem Mix meistens auch eine Rolle, und die Erfahrung der letzten 70 Jahr sagt, dass Maschinenkode bzw. eine marginal lesbarere Version davon (Assembler) keine für Menschen gute Ausdrucksform für Programme sind.
c-hater schrieb: > Bei batteriebetriebenen Anwendungen z.B. reicht es nämlich noch NICHT > aus, dass ein Programm einfach nur unter allen Umständen fehlerfrei > funktioniert Doch, das reicht aus. Ob das Programm jetzt 99.9% der Zeit oder nur 99.899999% der Zeit im Sleep ist, macht gar keinen Unterschied. Gerade bei Anwendungen, die die meiste Zeit im sleep sind, ist die Effizienz des Codes komplett egal.
c-hater schrieb: > Nein, hier ist eben eine der primären Forderungen, dass es nebenbei auch > noch die Batterie so wenig wie irgend möglich belastet. Denn hier kostet > jeder Takt programmerierischen Unvermögens schlicht bares Geld. Nicht > das des unfähigen Programmierers, sondern das des Anwenders... Sollte man dann nicht endlich dazu übergehen, Mobiltelefone in Assembler zu programmieren? Da geht es dauernd darum, wie man den Akku dazu kriegt, länger zu halten. Statt immer grössere Akkus einzubauen und deshalb im Note 7 mehrere Milliarden Dollar zu verlieren, müsste man bloss dich einstellen.
:
Bearbeitet durch User
c-nicht-hater schrieb: > Wenn ein C-Programm all das tut was es soll, gibt es keinen Grund es in > ASM zu schreiben. D.h. es ist hocheffizient. Das kommt drauf an, ob du Effizienz während der Programmierung oder zur Laufzeit brauchst. Wenn ein C-Programm tut was es soll, kann es noch so ineffizient geschieben sein, solange der Prozessor so schnell ist, dass er das durch seine Geschwindigkeit vor dem Nutzer verbergen kann.
A. K. schrieb: > Kann man es eigentlich auch als Interrupt betrachten, > wenn c-hater in eine harmlose Diskussion reingrätscht > und forthin nur noch über C vs ASM diskutiert wird? Das ist kein Interrupt, das ist eine Schnellabschaltung.
c-hater schrieb: > Bei batteriebetriebenen Anwendungen z.B. reicht es nämlich noch NICHT > aus, dass ein Programm einfach nur unter allen Umständen fehlerfrei > funktioniert (das halte ich sowieso für eine zumindest erstrebenswerte > Mindestforderung, nur in Kreisen der C&P-Programmierer hat man dazu > andere Meinungen), um das Prädikat "hocheffizient" zu verdienen. Nur ist dies bei Hochsprache eher möglich als bei Maschinensprache. Programmierer in Maschinensprache sind gezwungen sowohl Anwendung als auch die nativen Komponenten selbst zu programmieren. Es gibt da keine Skaleneffekte durch die Masse an Anwendern. Ob es eine ähnlich riesige Infrastruktur wie z.B. bei C gibt vage ich mal zu bezweifeln. Libs, Fachforen MISRA, Stackoverflow Pretest auf PC's etc ist C verschieden Compiler sind nun mal da. Das zu "hassen" ist neben den sinnlosen Emotionen in etwa so wie die Drehrichtung des Mondes um die Erde zu hassen oder die Farbe kirschrot. > > Nein, hier ist eben eine der primären Forderungen, dass es nebenbei auch > noch die Batterie so wenig wie irgend möglich belastet. Denn hier kostet > jeder Takt programmerierischen Unvermögens schlicht bares Geld. Nicht > das des unfähigen Programmierers, sondern das des Anwenders... Gibt sicher Projekte wo das mal zutreffen kann. Wenn aber die Assemblerprogrammierung das Projekt um die Kosten von 10 Batterien verteuert nützt die Einsparung von Energie im Promillebereich auch nichts mehr. Possetitjel schrieb: > Das ist kein Interrupt, das ist eine Schnellabschaltung. Aber 'ne ziemlich "verstrahlte" ;-).
In der Regel ist man damit, die Interrupts kurz zu halten in 99,99% der Fälle gut bedient. Alles andere erfordert eine Programmanalyse, d.h. welche Tasks sind alle auszuführen und wie schnell und wie oft. Kritisch sind Tasks, die z.B. Sound ausgeben, oder per SW-PWM Motoren oder LEDs steuern. Wenn da ein Jitter auftritt, hört man es, der Motor ruckelt oder die LEDs flackern. D.h. andere Interrupts dürfen diese Hauptinterrupts nicht merkbar verzögern. Fast alle MCs haben daher mindestens 2 Prioritätslevel, sogar die PICs. Nur bei den AVRs hat man sich lange dagegen gesträubt, erst neuere ATtiny erlauben einen hohen Level, allerdings nur für einen Interrupt. Braucht man keine jitterarmen Interrupts oder keine parallelen Tasks, sind selbst riesige 100ms im Interrupt kein Problem.
c-hater schrieb: > Naja, leicht zumindest bei Systemen wie dem AVR8... Moby nun wieder mit seinen AVRs. Können die Mods den Müll mal löschen?
Peter D. schrieb: > In der Regel ist man damit, die Interrupts kurz zu halten in 99,99% der > Fälle gut bedient. > Alles andere erfordert eine Programmanalyse, d.h. welche Tasks sind alle > auszuführen und wie schnell und wie oft. > Kritisch sind Tasks, die z.B. Sound ausgeben, oder per SW-PWM Motoren > oder LEDs steuern. Wenn da ein Jitter auftritt, hört man es, der Motor > ruckelt oder die LEDs flackern. D.h. andere Interrupts dürfen diese > Hauptinterrupts nicht merkbar verzögern. > Fast alle MCs haben daher mindestens 2 Prioritätslevel, sogar die PICs. > Nur bei den AVRs hat man sich lange dagegen gesträubt, erst neuere > ATtiny erlauben einen hohen Level, allerdings nur für einen Interrupt. > > Braucht man keine jitterarmen Interrupts oder keine parallelen Tasks, > sind selbst riesige 100ms im Interrupt kein Problem. Wenn die "schnellen" ISR nur ein Flag setzen, das dann von der Mainloop ausgewertet wird, dann ist das eh nichts anderes als das, was die HW macht. Reagiert die Hauptschleife, die gerade die 100ms "Intx-Bahandlungs-Code" ausführt in der Zeit auf das setzen anderer Flags? It depends, wie auch bei der HW-Variante. Es gibt Architekturen, die haben spezielle Features, um "ISR-only" Architektur zu unterstützen. Z.B. Cortex-M: nach ISR direkt wieder schlafen gehen, ohne Mainloop. Sowas würde man nicht in HW bauen, wenn es dafür keinen Bedarf gäbe.
Nop schrieb: > c-hater schrieb: > >> Naja, leicht zumindest bei Systemen wie dem AVR8... > > Moby nun wieder mit seinen AVRs. Können die Mods den Müll mal löschen? Der eine hasst C, scheint aber nicht ganz blöd zu sein, der andere ist Moby. ASM sind ihre einzige Gemeinsamkeit.
Wie oben schon erwähnt, ist "nur Flag setzen" natürlich Unsinn. Das tut die Hardware sowieso schon. Es geht also um eine Abwägung, was man sinnvollerweise in eine ISR direkt hinein packt, und was nicht. Das ist aber eine Einzelfallentscheidung, lässt sich nicht pauschalisieren. So wird man in einer mit Puffer im RAM betriebenen UART üblicherweise den Puffer in der ISR leeren/füllen. Das dauert nicht lang und das ist die richtige Stelle. Die Interpretation des Pufferinhalts jedoch, die gehört da eher nicht hinein. Bei Prozessoren mit verschachtelten Interrupts kann man bei komplexeren Anforderungen auch mit mehreren Ebenen für einen Interrupt arbeiten. Top/Bottom-Handler: Der kurze zeitkritische in Hardware getriggerte Top-Handler läuft mit hoher Priorität, erledigt das Wichtigste, und triggert anschliessend einen zweiten niedriger priorisierten Bottom-Handler für den Rest. Hoch priorisierte Handler kommen schnell durch, aber auch die weniger kritischen Bottom-Handler verhungern nicht durch eine träge Mainloop. Die Cortex M haben eine dafür gut geeignete PendSV-Exception. Wenn man richtig krasse Echtzeitanforderungen hat, und keine verschachtelten Interrupts, dann ist man in einer besonderen Situation und sitzt vielleicht sowieso auf dem falschen Pferd.
:
Bearbeitet durch User
A. K. schrieb: > Bei Prozessoren mit verschachtelten Interrupts kann man bei komplexeren > Anforderungen auch mit mehreren Ebenen für einen Interrupt arbeiten. Sowas habe ich mal beim 8051 für einen Tastverhältnismesser für den SMT160 gemacht. Der externe Interrupt bekam die hohe Priorität und der Timerüberlauf die niedrige. Im externen Interrupt wurde der Timer gestoppt und die Prioritäten umgedreht. Damit konnte der Timer seinen Überlauf dazwischen schieben. Danach wurden Timer und Überlaufzähler ausgelesen und für das Main zur Bearbeitung abgelegt. Hat super funktioniert, es gab keine Überlauffehler mehr.
Carl D. schrieb: > Der eine hasst C, scheint aber nicht ganz blöd zu sein, der andere ist > Moby. ASM sind ihre einzige Gemeinsamkeit. ASM wird 1:1 übersetzt, C kann (und wird, je nach Code und Compiler) im Verhältnis zu ASM von ausgezeichnet bis mies übersetzt. Dazu muß man sich aber .lss ansehen, ev. C neu codieren, .lss wieder ansehen, ev. neu codieren... Und dazu muß man aber auch fähig sein... Mehr wollte c-hater auch nicht sagen, glaube ich.
> Wie oben schon erwähnt, ist "nur Flag setzen" natürlich Unsinn. > Das tut die Hardware sowieso schon Es gibt nicht nur Chip-Interne Hardware. Ein Klassiker wäre zum Beispiel der externe Ethernet Controller, der ein Interrupt Signal an die CPU sendet, wenn er bedient werden möchte. Die ISR setzt dann nur ein Flag im RAM, damit die Hauptschleife nicht bei jedem Durchlauf den Status vom Ethernet Controller über seine serielle Schnittstelle holen muss. Je mehr Hardware dieser Art von einer CPU bedient wird, umso mehr fällt der Unterschied zwischen "Flash im RAM abfragen" und "Flag aus externem Chip auslesen" ins Gewicht.
Stefan U. schrieb: > Ein Klassiker wäre zum Beispiel > der externe Ethernet Controller, der ein Interrupt Signal an die CPU > sendet, wenn er bedient werden möchte. Auch in diesem Fall gibt es ein Flag im Interruptcontroller der CPU. Das hat nichts mit extern/intern zu tun.
Thomas E. schrieb: > c-hater schrieb: >> Genau nur zwei: >> >> 1) Inkompetenz der Hochsprachen-Programmierer >> 2) Insuffizienz und Ineffizienz der Hochsprachen > > Warum meinst du eigentlich, Hochsprachenprogrammierer und insbesondere > C-Programmierer, ständig zu Idioten erklären zu müssen? > > Was danach kommt ist doch völlig in Ordnung. Das liest nur keiner mehr, > weil er bei den ersten Sätzen schon die Schnauze voll hat von deiner > blöden Anmache. Faszinierend :) Ich fühle mich richtig ertappt. C-dingens Beitrag kurz angelesen und dann abgehakt. Seine Art sorgt wirklich für ein Minimum an Leseaufmerksamkeit.
Interrupts sind dafür da, schnell reagieren zu können. "Flag setzen" ist so ziemlich das Gegenteil davon, weil das Zeitverhalten der Reaktion auf den Interrupt dann voll von der Mainloop definiert wird. Und genau das will man mit Interrupts ja vermeiden. Das kann sich sehr konkret auswirken, zwei Beispiele: So ist man zwar mit Capture-Registern von Timern besser dran als mit dem Auslesen des Counters, aber manchmal gehts nicht anders (siehe Peters Beitrag). Da muss man im Handler lesen oder den Timer stoppen, sonst Quatsch. Bei AVRs als I2C-Slave hängt das Zeitverhalten der Schnittstelle extrem von der Interrupt-Latenz ab. Genauer: Von der Latenz zwischen dem Setzen des Int-Flags durch die Hardware und den Zurücksetzen davon durch die Software. Dazwischen gibts clock stretching, sofern enabled. Zurücksetzen darf man das Flag aber erst, wenn die zur aktuellen Phase der TWI State Machine gehörende Aktivität durchgeführt wurde (Adresse prüfen, Daten abholen, etc). Macht man das in der Mainloop, bremst man den Master massiv aus, u.U. bis zum Timeout. Wenn man also I2C nebenläufig betreibt um damit nicht die Mainloop zu blockieren, dann müssen die Kernaktivitäten des TWI direkt in den Interrupt-Handler rein. So ist das auch gedacht. Hat man ein preemptive RTOS im Einsatz und versteht unter "Flag setzen" die Aktivierung des zugehörigen Threads, dann sieht das wieder anders aus. Das ist zwar langsamer als die Verarbeitung im Handler, kann aber ausreichen und übersichtlicher sein. In so einer Konfiguration bietet sich aber auch die erwähnte Top/Bottom-Struktur an, mit der kritischsten Aktivität im Handler und dem Rest im Thread.
:
Bearbeitet durch User
> Auch in diesem Fall gibt es ein Flag im Interruptcontroller der CPU. > Das hat nichts mit extern/intern zu tun. Ach ja, du bist ganz woanders. Ich hatte dich missverstanden.
Marc V. schrieb: > Carl D. schrieb: >> Der eine hasst C, scheint aber nicht ganz blöd zu sein, der andere ist >> Moby. ASM sind ihre einzige Gemeinsamkeit. > > ASM wird 1:1 übersetzt, C kann (und wird, je nach Code und Compiler) > im Verhältnis zu ASM von ausgezeichnet bis mies übersetzt. > Dazu muß man sich aber .lss ansehen, ev. C neu codieren, .lss wieder > ansehen, ev. neu codieren... > Und dazu muß man aber auch fähig sein... > > Mehr wollte c-hater auch nicht sagen, glaube ich. Ist aber für die Beantwortung der Frage "ist Moby der c-hater?" sowas von uninteressant.
Carl D. schrieb: > "ist Moby der c-hater?" Gibt es den denn noch, den Moby? C-hater hat aber immer was zu ASM zu sagen, während ich von Moby immer nur Sprüche gehört habe. C-hater, man mag ihn mögen oder nicht, er weiß aber wovon er spricht.
F. F. schrieb: > Carl D. schrieb: >> "ist Moby der c-hater?" > > Gibt es den denn noch, den Moby? > C-hater hat aber immer was zu ASM zu sagen, während ich von Moby immer > nur Sprüche gehört habe. C-hater, man mag ihn mögen oder nicht, er weiß > aber wovon er spricht. Letzteres hatte ich erwähnt. Moby ist ab&zu hier, meist aber auch gleich wieder gelöscht und leicht an seinem Wortschatz erkennbar.
F. F. schrieb: > Gibt es den denn noch, den Moby? Anzunehmen, aber hier ist er m.W. hochkant rausgeflogen.
@ A. K. (prx) >> Gibt es den denn noch, den Moby? >Anzunehmen, aber hier ist er m.W. hochkant rausgeflogen. Wurde er nach Assemblistan entsorgt? ;-)
Beitrag #5148060 wurde von einem Moderator gelöscht.
Beitrag #5149291 wurde von einem Moderator gelöscht.
Beitrag #5149296 wurde von einem Moderator gelöscht.
Beitrag #5149304 wurde von einem Moderator gelöscht.
Beitrag #5149307 wurde von einem Moderator gelöscht.
Beitrag #5149310 wurde von einem Moderator gelöscht.
Beitrag #5149312 wurde von einem Moderator gelöscht.
Beitrag #5149317 wurde von einem Moderator gelöscht.
Beitrag #5149322 wurde von einem Moderator gelöscht.
-Moby- schrieb im Beitrag #5149291: > Da macht Euch mal keine Sorgen. > Den entsorgt hier so schnell keiner. > Freilich muß ich den selbsternannten "Hochsprache ist ja so toll"- > Profis nun unter tausend anderen Namen Feuer unterm Arsch machen ... Was > diesen Thread betrifft fühle ich mich durch C-Hater allerdings bestens > vertreten :-) Wie drollig! Der Honk (Hauptschüler Ohne Nennenswerte Kenntnisse - Moby) verbrüdert sich mit dem älteren Herrn (c-hater), der darüber vergrämt, daß sein einstmals mit viel Schweiss erworbenes Wissen heute nur noch begrenzten Wert hat.... Tja....wer nicht mit der Zeit geht, geht mit der Zeit. Bezeichnend finde ich, daß Beide seit Monaten mit einem Gast-Account ihren Frust an den innovativeren Leuten abbauen.... @c-hater: dein fundiertes Grundlagenwissen zeigt, daß du bereits sehr lange dabei bist, aber scheinbar hast du irgendwann den Anschluss verloren....dumm gelaufen - aber bitte laß deinen Frust nicht an uns aus, und sieh zu, daß du die Zeit bis zur Rente halbwegs stressfrei überstehst! ;)
Beitrag #5149331 wurde von einem Moderator gelöscht.
Beitrag #5149340 wurde von einem Moderator gelöscht.
Beitrag #5149344 wurde von einem Moderator gelöscht.
Beitrag #5149347 wurde von einem Moderator gelöscht.
Beitrag #5149348 wurde von einem Moderator gelöscht.
Beitrag #5149351 wurde von einem Moderator gelöscht.
Beitrag #5149352 wurde von einem Moderator gelöscht.
Beitrag #5149367 wurde von einem Moderator gelöscht.
Beitrag #5149373 wurde von einem Moderator gelöscht.
Beitrag #5149374 wurde von einem Moderator gelöscht.
Beitrag #5149375 wurde von einem Moderator gelöscht.
Beitrag #5149419 wurde von einem Moderator gelöscht.
Beitrag #5149420 wurde von einem Moderator gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.