PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : (Maximale) Größe einer Interrupt Service Routine



Psiyou
16.01.2006, 15:51
Hallo,

ich würde gern mal wissen was so erfahrungsgemäß (oder gibt es dazu noch eine andere Grundlage?) eine maximal / vernünftige Größe für eine Interruptfunktion ist. Man sagt ja immer das diese möglichst kurz seien sollen damit man keine andern Interrupts verpasst.

Nun möchte ich aber gerne Daten, die über die serielle Schnittstelle reinkommen, am liebsten direkt in der ISR auswerten um mir Speicherplatz zu sparen (geht um PDU formatierte SMS vom Mobiltelefon).
In der ISR würde eine Art Zustandsautomat mit switch/case laufen der die Daten entsprechend aufbereitet und gegebenenfalls abspeichert.
Von der "normalen" Variante mit einem Buffer und anschließendem, bzw. teilweisem Auswerten würde ich gerne Absehen da das ganze später in einer zeitgesteuerten Multitaskingumgebung laufen soll, und sich so die Buffergröße je nach Anzahl der Tasks ändern würde.

Hoffe es ist klar geworden was ich meine und schon mal vielen Dank im Voraus
Philipp

PicNick
16.01.2006, 16:09
Nun, so eine heilige Kuh ist das auch nicht.
Es sollen in der Zeit, die eine ISR-Routine verbraucht, keine anderen Interrupts auftreten (können), da sie ja dann nicht bearbeitet werden.
Und das gilt auch nur dann, wenn sie entweder zeitkritisch sind, oder wenn sie in der blockierten Zeit mehrfach auftreten können.
Klingt theoretisch, is aber eh' logisch.
"das tut man nicht" ist kein Argument, daß dich interessieren müßte.

Psiyou
16.01.2006, 16:33
@PicNick
Hab mit ISR noch nicht wirklich viel gearbeitet, bzw hatte noch nie den Fall das sich zwei oder mehr gleichzeitig laufen hatte.

Soll heißen, wenn ich das so mache, muss ich dafür sorgen das die maximale laufzeit der ISR klein genug ist das andere ISR die während der Laufzeit aktiviert werden im Anschluß noch ihrerseits den code abarbeiten können bevor ein weiterer Interrupt ausgelöst wird. Oder anders rum, alle anderen Intrrupts dürfen nicht häufiger auftreten als es oben genannte Bedingungen zulassen.
Sprich wenn ich zB. noch über die I²C Schnittstelle komuniziere muss dies entsprechend langsam passieren.
Gibt es da eigentlich irgend ein tolles Tool zu das solche Laufzeiten von ISR (mit aufruf etc) angeben kann ?? zB in Takten ? (vorrausgesetzt es sind keine Schleifen mit sich ändernden Durchläufen dabei).

Philipp

PicNick
16.01.2006, 18:25
Das siehst du eigentlich völlig richtig.
Etliche Simulatoren und Debugger geben Takte an. Ich persönlich hab bei solchen Fragen gerne etwas Spielraum, rechne also nur ungefähr.
Beispiel:
Bei 9600 Baud braucht ein Byte ca 1 mS über die Leitung. Das ist die minimal Zeit, die ich habe bis zum nächsten Byte.
Ein 8MHZ Controller macht in der Zeit 8000 Takte, das ist eine ganze Menge Code (samt einigen Schleifen). Die brauch man normalerweise nicht, um das Byte irgendwo hinzuräumen.
I2C ist ca 10 mal so schnell bei 100 kHz. Also ein paar Byte über I2C senden ist da immer drin.
Ich wett' schon, daß du früh genug aus deiner ISR wieder rauskommst.
Wenn's soweit ist, daß du wirklich die Takte zählen mußt, ob's grad noch geht oder nicht, dann solltest du aber wirklich was anderes überlegen.

Alles hat Grenzen, auch die genannte Lehrmeinung von kurzen ISRs kommt ja nicht von ungefähr. Aber, wie gesagt, das ist kein göttliches Gebot

Psiyou
17.01.2006, 10:27
Prima, vielen Dank.
Dann werd ich das jetzt mal so umsetzen. Hatte nur noch mal nachgefragt weil ich mir wirklich nicht sicher war und wollte am Ende ungern feststellen das es alles nicht wie gehofft zusammenspielt.

Danke
Philipp

SprinterSB
23.01.2006, 16:40
Die "Länge" einer ISR ist eigentlich nicht wichtig, sondern eher ihre Dauer ;-)

Falls andere IRQs währent dessen auftauchen, gehen die auch nicht verloren, sondern werden nach Beenden der ISR abgearbeitet. Alternativ kannst du irgendwo in deiner ISR mit sei() die Interrupts wieder frei geben und geschachtelte Interrupts zulassen. Tritt innerhalb der ISR wieder ihr eigener IRQ auf, hast du jedoch ein Problem. Evtl hilft dann, die Interrupts erst freizugeben, nachdem nur die jeweils eigene IRQ deaktiviert wurde. Am Ende des ISR werden Interrupts mit cli() deaktiviert, das Signal wieder aktiviert und die ISR verlassen.

Welchen Weg du wählst hängt von deiner Software-Struktur ab und von den Zeiten, die du einhalten musst.

In einer Applikation hab ich eine ISR-Rate von 16kHz und eine ISR dauert bis zu 750 Zyklen (da sind die Zeiten für die geschachtelten ISRs schon dabei).
Die Zeiten sind Erfahrungswerte. Die (Maximal-)Werte der Zeiten besorge ich mir in der Applikation selbst, weil das in einem Simulator nicht möglich ist, weil ich da die anderen Interrupt-Quellen nicht hab (Fernbedienung, UART, etc)

Psiyou
26.01.2006, 21:51
Hi,

ja, hast recht, hab mich da nicht korreckt ausgedrückt. Meinte die Dauer :)
Aber mal eine Frage zu Deiner Messmethode. Schaltest ein Portpin ein wenn Du in die ISR gehst und nach beenden wieder aus ? (und dann mit Oszi dran)
Oder gibts da was besseres ? Bei der Variante fällt mir so spontan auf das man damit Probleme bekommt wenn sich die Zeiten stark unterscheiden.

SprinterSB
27.01.2006, 11:38
Zie Zeitmessung mach ich direkt am Timer, weil es sich in meinem Fall um einen Timer-Interrupt handelt, der mit bis zu 20kHz reichen kann. Die Ausgabe erfolgt auf Anfrage über ein Display oder auf Anfrage via UART auf ein Terminal.

Das über einen Simulator zu messen stell ich mir aus den o.g. Gründen nicht so einfach vor -- immerhin will man realistische Werte, und da sollte man schon in vivo messen. Ausserdem nutzt einen die reine Zeitmessung nicht viel, was interessiert sind eher die Maximalzeiten.

Meine Lösung hat den Nachteil, daß man einen Timer in linearem Betrieb braucht (ein Timer, der in PWM mit up-down betrieben wird, ist nicht anzapfbar bzw für Zeitmessung nutzlos), die Quelle anpacken muss und Resourcen für die Messung braucht. Da die ISRs recht komplex sind und geschachtelt sein können, stell ich mir -- wie du auch -- recht schwer vor, da mit einem Oszi was zu sehen (Quelle anpacken muss man da auch).

Dramatisch ist der Resourcenverbrauch nicht, ein Register für den Timerwert und einzweites für den Maximalwert. Neuen Timerwert lesen, Differenz bilden, mit Maximum vergleichen und ggf. neues Max speichern.

Falls der Timer während der Messung überläuft (abhängig von den Rahmenbedingungen, Applikation, ...) muss man das erkennen können und auch, wie oft er überläuft.

Extern geht vielleicht was mit einer Schaltung. Über einen Port lädt man einen C und erzeugt eine Rampe, die für kleine Zeiten linear ist. Die Spannung gibt man in einen Komparator, der mit dem bisherigen Maximalwert vergleicht und diesen als Spannung zur Verfügung stellt. Entladen des C auf fallende Flanke am Port. Machbar ist das bestimmt, aber ad hoc ne Schaltung nennen kann ich jetzt auch nicht.