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.
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?
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?
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.
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.
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.
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.
> 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.
-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! ;)