Gibt es verfügbare Richtlinien für die Codemenge in einem kritischen Abschnitt der Interrupt-gesteuerten Verarbeitung?
Meine persönliche Faustregel lautet, dass der kritische Teil (dh der zwischen dem Deaktivieren von Interrupts und dem Aktivieren von Interrupts) jeder Interrupt-gesteuerten Verarbeitung nicht mehr als etwa ein Dutzend Codezeilen umfassen sollte (einschließlich der in jeder aufgerufenen Funktion/Bibliothek/Makro). ) und dass die Verarbeitung so linear wie möglich sein sollte.
Ich würde etwas in der Art erwarten:
disable_interrupts
if error_condition:
set_error_flag
else:
small_data_transfer
set_ready_flag
enable_interrupts
Ich wurde jedoch gebeten, ein bestehendes Projekt zu untersuchen, bei dem einige der Interrupts Handler haben, bei denen die Anrufdiagramme nicht auf ein Blatt A1 passen (alles im kritischen Abschnitt).
Um dies zu verdeutlichen, handelt es sich um ein "Bare-Metal"-Projekt ohne implementiertes Betriebssystem/Scheduler - und alle Interrupt-Handler beginnen mit dem Deaktivieren aller Interrupts - d ein Deaktivierungs-/Aktivierungsabschnitt). Es gibt eine Vielzahl von Interrupts und Hardwareabhängigkeiten, aber soweit ich sehen kann, werden einige der ISRs Tausende von Zeilen innerhalb des "kritischen" Abschnitts ausführen.
Ich weiß, dass dies ein Problem ist und wirklich komplett neu geschrieben werden muss, aber ich kann keine Standards finden, einschließlich MISRA, auf die ich verweisen kann, anstatt nur " nach meiner Erfahrung " zu sagen - um das Projektmanagement zu überzeugen, auf das ich hinweisen muss einige anerkannte Standards.
Daher meine Frage: Kann mich jemand auf Standards oder Richtlinien hinweisen, die ich verwenden kann, um meine Erfahrung zu untermauern? (Oder liege ich natürlich total falsch).
Im Allgemeinen ist die Verteilung der CPU-Zeit zwischen ISR-Code und Nicht-ISR-Code sehr anwendungsabhängig.
Wenn die meiste Arbeit in Nicht-ISR-Code erledigt wird, dann ja, Sie möchten die ISRs im Allgemeinen so kurz wie möglich halten (aber nicht kürzer, um ein berühmtes Zitat zu paraphrasieren).
Ich habe jedoch harte Echtzeit-DSP-Anwendungen gesehen (und gebaut), in denen 90% der Arbeit in der ISR erledigt wird und der Nicht-ISR-Code nur Aufgaben behandelt, die nicht zeitkritisch sind, wie Konfiguration, Status und Benutzeroberfläche.
Beide Ansätze sind in tief eingebetteten Systemen vollkommen gültig.
Als allgemeine Richtlinie gilt, dass kritische Abschnitte so kurz wie möglich sein sollten.
Was Sie wirklich tun müssen, ist die Länge des kritischen Abschnitts zu berücksichtigen, wenn Sie die Planbarkeit des Aufgabensatzes überprüfen. Das hängt davon ab, wie Sie die Aufgaben planen, aber ich denke, es könnte so einfach sein, wie die Ausführungszeit des kritischen Abschnitts zur Ausführungszeit jeder Aufgabe mit niedrigerer Priorität hinzuzufügen.
Ich denke, Sie müssen die Ausführungszeit des unterbrechungsfreien Codes bezüglich der schnellsten Reaktionszeit (Latenz) und Variabilität dieser Zeit (Jitter) berücksichtigen, die Sie vom Mikrocontroller benötigen. Es mag nicht intuitiv sein, was das ist – es kann etwas sein, das „dringend“, aber nicht „wichtig“ ist.
Zum Beispiel musste ein Controller, den ich vor einigen Jahren entworfen hatte, mit RS-232-Eingängen umgehen, den Ausgang mit dem Steueralgorithmus aktualisieren, den Dual-Slope-ADC steuern, ein LED-Display und eine Tastatur scannen (einschließlich Entprellen) und schreiben ein langsames EEPROM, und um einen elektromagnetischen Piepser zu steuern (und wahrscheinlich habe ich noch ein paar andere Dinge, die ich vergessen habe). Es stellte sich heraus, dass die kritischste Reaktionszeit die periodische Unterbrechung des Piepsers (alle 250 us) war, gefolgt von der LED-Anzeige, hauptsächlich aus kosmetischen Gründen. Wenn also 10 % Jitter im Pieper-Toggle akzeptabel waren, sind das 25 usec an unterbrechungsfreiem Code (was nicht viele Anweisungen waren, aber genug, um bestimmte Dinge atomar zu machen). Dieser spezielle Prozessor unterstützte verschachtelte Interrupts, so dass IIRC I den periodischen Interrupt-Code nach dem ersten Abschnitt reentrant machte.
Wenn Sie anstehende Interrupts während langer Codeabschnitte verschieben, kann es in Ordnung sein, wenn Ihre Anforderungen an Latenz und Jitter in Bezug auf die Ausführungszeit der "kritischen Teile" ziemlich entspannt sind.
Mein üblicher Ansatz besteht darin, die Codeausführungszeit in ISRs zu minimieren und so schnell wie möglich zurückzukehren (vielleicht Dinge wie entprellte Eingabeereignistokens in kreisförmige Warteschlangen zu stopfen, Flags zu setzen und auszusteigen). Wenn beispielsweise ein komplexer Steueralgorithmus alle 200 ms mit maximal 20 ms Jitter ausgeführt werden muss, würde ich alle 200 ms ein Flag im Timer-Interrupt setzen und dieses Flag außerhalb des ISR abfragen.
Abgesehen von der Erfüllung der Designanforderungen wird die Zuverlässigkeit durch diesen Ansatz verbessert.
Soweit es darum geht, eine Art Richtlinie zu finden, die dies besagt, schlage ich vor, sich einige der Richtlinien für sicherheitskritische Software anzusehen. Möglicherweise finden Sie es nicht direkt angegeben, aber Sie können es möglicherweise aus anderen Aussagen ableiten. UL1998 IEC 60730 usw. In diesem FAA-Dokument heißt es:
Interrupts und deren Auswirkung auf Daten müssen in sicherheitskritischen Bereichen besonders beachtet werden. Die Analyse sollte verifizieren, dass Unterbrechungen und Unterbrechungsbehandlungsroutinen keine kritischen Datenelemente verändern, die von anderen Routinen verwendet werden.
Und
Von besonderer Bedeutung für die Sicherheit ist die Sicherstellung der Integrität sicherheitskritischer Daten gegen versehentliche Änderung oder Überschreibung. Überprüfen Sie beispielsweise, ob die Interrupt-Verarbeitung sicherheitskritische Daten stört.
Beides wird schwieriger, wenn die Größe des Unterbrechungscodes zunimmt.
Kurze (in Bezug auf maximalen Jitter und Latenz) häufige Interrupts können als effektive Verringerung der Prozessorgeschwindigkeit analysiert werden, anstatt sich mit schlimmsten Anhäufungen langer Interrupts zu den kritischsten Zeiten auseinandersetzen zu müssen, was ebenfalls für eine schnelle Ausführung spricht als einfacher Code innerhalb von ISRs.
Das Vermeiden von Verschachtelungsinterrupts erscheint mir nicht allzu schlimm oder sogar absurd. Tatsächlich können verschachtelte Interrupts mehr Probleme verursachen, als sie lösen.
Ich beziehe mich speziell auf den Speicher, der zum Speichern/Wiederherstellen des Kontexts beim Betreten/Verlassen der ISR verwendet wird. Üblicherweise speichert jede ISR auf einfachen Architekturen den gesamten erforderlichen Kontext des Codes, den sie unterbrochen hat, beispielsweise auf dem Stapel des Prozessors. Bei der Entwicklung der Software muss dieser Speicher berücksichtigt werden.
Wenn zum Beispiel ISR A 10 Bytes Kontext zum Speichern/Wiederherstellen benötigt, ISR B 15 und ISR C 12 Bytes benötigt, lautet die Berechnung/Schätzung einfach:
Irgendwo während der Ausführung von nicht kritischen Abschnitten kann irgendeine der ISRs ausgelöst werden. Wenn nun die ISRs nicht verschachtelt werden dürfen, beträgt der für den Kontext erforderliche maximale Speicher max( 10, 15, 12 )
= 15 Bytes. Wenn jede der ISRs jede andere dieser 3 ISRs unterbrechen kann, sind im schlimmsten Fall 10 + 15 + 12
= 37 Bytes Kontext, die gleichzeitig gespeichert werden müssen . Daher muss zu jedem Zeitpunkt während der Ausführung (von nicht-atomarem Code) mindestens genug Speicher für diese 37 Bytes Kontext verfügbar sein, gegenüber 15 im Fall der Nichtverschachtelung.
Je mehr ISRs sich dem „Verschachtelungsspiel“ anschließen, desto deutlicher wird das Problem natürlich sichtbar.
Wenn mehrere Tasks gleichzeitig ausgeführt werden und ISRs den Kontext im aktuellen Stapel des Codes speichern, den sie unterbrechen, müssen Sie eine Kontextgröße für den schlimmsten Fall pro Task berücksichtigen .
Dieses Argument hängt natürlich von der verwendeten HW-Architektur ab. Es ist möglicherweise nicht anwendbar, wenn der HW/Interrupt-Controller fortgeschrittener ist und spezielle Merkmale aufweist, um den Kontextwechsel zu/von ISRs zu handhaben.
Abgesehen davon erfordern komplexe ISRs tendenziell mehr Kontextdaten, die gespeichert/wiederhergestellt werden müssen, als einfache, sodass kleine, prägnante ISRs normalerweise empfohlen werden, da sie mehrere Vorteile bieten:
Wenn am Ende alle ISRs auf ihr Minimum reduziert werden, wie wenn nur ein Flag gesetzt wird, kann die Frage, ob das Verschachteln von ISRs zulässig ist oder nicht, eindeutig zugunsten des Nicht-Verschachtelns beantwortet werden, da der Vorteil des Verschachtelns von ISRs verschwindet.
Connor Wolf
Connor Wolf
David Tweed
Steve Barnes
Löffel
David Tweed
Steve Barnes
David Tweed
Steve Barnes
David Tweed
Steve Barnes
Rev