Hi, beim Versuch das Interruptsystem des STM32 zu verstehen, bin ich leider an einer Stelle etwas Ratlos?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
Was sind Events? In wie fern hängen sie mit den Systeminterrupts zusammen? Gruß Tom
|
Anzeige
|
STM32: Interrupts vs. Events?Hi, beim Versuch das Interruptsystem des STM32 zu verstehen, bin ich leider an einer Stelle etwas Ratlos?
Was sind Events? In wie fern hängen sie mit den Systeminterrupts zusammen? Gruß Tom Hallo Tom, soweit ich das verstanden habe, dienen die Events dem 'vermeiden' der ISR. Der Controller soll durch einen Event aus dem Schalf gerissen werden, ohne aber die anschließende Behandlung durch innerhalb der ISR auszlösen. Die Programmausführung soll dynamisch auf so ein 'Event' reagieren können, je nach dem, ob es gerade zeitlich passt oder nicht. Das setzt ein Event-'Betriebssystem' vorraus. MfG Events sind neben Interrupts etwas, das dem Cortex Core seinen Schlaf rauben kann. Wenn der also in irgendeinem Sleep-Mode pennt und dafür WFE verwendet hat, dann können ihn auch Events aufwecken. Siehe Kapitel 2.5 in PM0056. Wobei man bei der Lektüre etwas kreativ denken muss. So steht dort "The processor provides an external event input signal" ohne zu erwähnen, dass dieses "external" auch intern generiert sein kann. Wohl aus der Perspektive des Cores zu sehen, für den alles ausserhalb seiner selbst "extern" ist. Mit solchen Events lässt sich beispielsweise das Problem verlorengehender Ereignisse vermeiden. Bei sleep modes tritt nicht selten ein Problem auf, wenn der Controller drauf und dran ist sich schlafen zu legen und exakt davor das Ereignis auftritt, das ihn wieder aufwecken soll. Diese race condition sollte man bei sleep modes egal welcher Controller immer im Auge behalten. Bei AVRs löst man das Problem, indem man erst unmittelbar vor dem SLEEP-Befehl die Interrupts freigibt und dies im Prozessor einen Befehl verzögert erst mit dem SLEEP-Befehl wirksam wird. Andere Prozessoren besitzen deshalb SLEEP-Befehle mit eigener Interrupt-Steuerung. Beim Cortex sieht das etwas anders aus. Man kann m.W. die Priorität nicht exakt gleichzeitig zum WFI-Befehl setzen, so dass man in ein Dilemma gerät. Wenn man die Priorität so setzt, dass der Handler nicht vor WFI durchkommt, dann wacht er auch im WFI nicht auf. Wenn man sie so setzt, dass der Interrupt durchkommt, dann läuft die ISR u.U. unmittelbar vor dem WFI-Befehl und der Controller legt sich danach über den WFI-Befehl schlafen. Wenn dieser Interrupt ihn jedoch dauerhaft aufwecken sollte, dann verpennt der Controller. Mit dem Event-Bit löst sich das Problem, indem der betreffende Interrupt dieses Bit setzt und man für den sleep mode WFE verwendet. Dieser Befehl ist bei gesetztem Bit wirkungslos und der Controller pennt nicht ein. D.h. für die normale Programmierung brauche ich die Events gar nicht, da nehme ich einfach die Interruptregister wie gewöhnlich. Gruß Tom Die Verwendung der eigentlich für multicores vorgesehenen events des Cortex-M3 cores für wakeup aus sleep modes scheint eine Besonderheit der STM32 zu sein. Jedenfalls bin ich etwas Vergleichbaren bei den LPC1000 nicht begegnet. Es würde mich folglich interessieren wie das Problem der oben skizzierten race condition bei den LPC1000 gelöst wird. SEVONPEND=1 oder SEV im Handler. A. K. schrieb: > Bei sleep modes tritt nicht > selten ein Problem auf, wenn der Controller drauf und dran ist sich > schlafen zu legen und exakt davor das Ereignis auftritt, das ihn wieder > aufwecken soll. Diese race condition sollte man bei sleep modes egal > welcher Controller immer im Auge behalten. Dieses Problem wurde aber erst durch eine völlig unsinnige Empfehlung in den Atmel Datenblättern provoziert. Das Sleep Enablen direkt vor dem Sleep ist großer Quatsch und führt fast unweigerlich zum Deadlock. Wenn man im Main den Sleepmode zuerst, d.h. vor dem Interrupt enabled und der Interrupt den Sleepmode disabled, ist alles in Butter. Egal, wer zuerst kommt. Peter Peter Dannegger schrieb: > Wenn man im Main den Sleepmode zuerst, d.h. vor dem Interrupt enabled > und der Interrupt den Sleepmode disabled, ist alles in Butter. Egal, wer > zuerst kommt. Das löst das zugrunde liegende Problem nur teilweise. Denn auch bei abgeschaltetem sleep mode läuft der Controller nach dem einen Hauch zu früh eintreffenden Interrupt sofort in den SLEEP Befehl rein. Zwar dann ohne Tiefschlaf, aber dennoch reagiert die Hauptschleife nun nicht auf die Tätigkeit, die von der ISR möglicherweise dort angestossen wurde. Erst wenn der nächste Interrupt kommt geht es wie vorgesehen weiter. Dieses Problem ist grundsätzlicher Natur, nicht auf AVRs beschränkt und nicht auf Powersave-Modi. Sobald zwischen der Freigabe des Interrupts und dem folgenden SLEEP/WAIT/HALT/... eine Lücke auftritt durch die ein Interrupt schlüpfen kann hat man dieses Problem. PIC18 schaltet im entsprechenden Befehl die Interrupts selbst ein, andere reagieren wie AVR und ARM7/9(*) bei der Freigabe der Interrupts erst mit dem Folgebefehl, 68K läd darin die Interrupt-Priorität, ... Die Event-Variante der Cortex-M3 weicht jedoch von diesem klassischen Prinzip ab. Es ist die einzige mir bekannte Variante, in der es ohne Abschaltung der Interrupts (oder Code im RAM) sauber lösbar ist, und das ist wohl auch der Sinn der Sache. Der Latenzzeit zuliebe. *: Dessen "surprise interrupt" bei abschaltenden Interrupts ist die direkte Folge dieser Strategie. A. K. schrieb: > Das löst das zugrunde liegende Problem nur teilweise. Denn auch bei > abgeschaltetem sleep mode läuft der Controller nach dem einen Hauch zu > früh eintreffenden Interrupt sofort in den SLEEP Befehl rein. Zwar dann > ohne Tiefschlaf, aber dennoch reagiert die Hauptschleife nun nicht auf > die Tätigkeit, die von der ISR möglicherweise dort angestossen wurde. > Erst wenn der nächste Interrupt kommt geht es wie vorgesehen weiter. Dann ist dort der Sleep-Befehl grundsätzlich anders als beim AVR. Wird beim AVR der Sleepmode disabled, arbeitet der Sleep-Befehl nur wie ein NOP, d.h. da wartet nichts. Will man aber auf einen Interrupt warten, wird der Sleepmode direkt nach dem letzten Sleep enabled. Kommt dann bis zum nächsten Sleep kein Interrupt, wartet das Sleep. Dadurch geht keine Nachbehandlung eines Interrupt im Main verloren. > Die Event-Variante der Cortex-M3 weicht jedoch von diesem klassischen > Prinzip ab. Dann muß aber nach dem Sleep das Interruptflag noch händisch gelöscht werden. Peter Peter Dannegger schrieb: > Wird beim AVR der Sleepmode disabled, arbeitet der Sleep-Befehl nur wie > ein NOP, d.h. da wartet nichts. Yep, dann löst sich das Problem. Das scheint mir aber die Ausnahme zu sein. Bei den meisten Architekturen wartet der entsprechende Befehl immer auf eintreffende Interrupts, konfigurierbar ist nur die Frage, wie tief er dabei schläft. > Dann muß aber nach dem Sleep das Interruptflag noch händisch gelöscht > werden. Wenn WFE durch ein Event aufgeweckt wird, dann wird das Event-Bit dadurch automatisch gelöscht. Das ist auch gut so, denn sonst würde man auch wieder in einer race condition landen. Interrupt-Flags müssen nicht gelöscht werden, weil nicht unbedingt welche gesetzt werden, wenn das Ereignis nur aufwecken soll. Jedenfalls nicht auf dem STM32, denn das Event-Signal an den Core ist transient (Puls), zum Event-Bit wird es erst im Core. Bei anderen Controllern auf Cortex-Basis sieht das etwas anders aus, da die zwar das Event-Bit ebenfalls dafür verwenden, aber das Event nicht wie STM32 im EXTI separat auslösen können, sondern nur über Interrupts. Kann sein, dass man in irgendwelchen Devices nachbearbeiten muss. Vielleicht will man ja auch in die dazu gehörende ISR reinlaufen, aber erst nachdem im Rahmen des Aufweckvorgangs wieder der richtige Takt usw. aktiviert wurde. An diesem Beispiel sieht man, daß es in verschiedenen MCs auch verschiedene Wege gibt, eine bestimmte Aufgabe zu lösen. Daher ist es doch nicht so leicht, schnell mal eben zwischen verschiedenen MCs zu wechseln. Und es ist besser, wenige MCs richtig zu beherrschen, als viele nur halb. Denn nur dann kann man auch zuverlässige Programme schreiben. Man muß sich schon eingelesen haben, wie der MC intern arbeitet, damit man den Programmablaufplan fehlerfrei erstellen kann. Ich muß auch sagen, Hut ab, wer die Interruptlogik der ST-ARM7 vollständig verstanden hat (ich habe es nämlich nicht). Peter Peter Dannegger schrieb: > Ich muß auch sagen, Hut ab, wer die Interruptlogik der ST-ARM7 > vollständig verstanden hat (ich habe es nämlich nicht). Die Timer vom STM32 sind auch nicht übel ;-). Ich kann deshalb Controller dieser Klasse auch nicht für den Einstieg empfehlen, mmvisuals missionarischem Eifer zum Trotz. Peter Dannegger schrieb: > Ich muß auch sagen, Hut ab, wer die Interruptlogik der ST-ARM7 > vollständig verstanden hat (ich habe es nämlich nicht). ST ARM7 wäre ja wohl STR7, also den EIC. Hab grad kurz reingesehen - verglichen mit dem Krampf den NXP über die ARM PrimeCells in die LPC2000 eingebaut hat (und ST in den STR9, und das auch noch doppelt) ist das Teil doch prima, und vor allem besser dokumentiert. A. K. schrieb: > ST ARM7 wäre ja wohl STR7, also den EIC. Ja, ist schon einige Jährchen her, daß ich ihn mir angeguckt habe. > und vor allem besser dokumentiert. Ja, 35 Seiten über die Interruptlogik ist schon sehr beeindruckend. Und dann die vielen Note, Avoid, Caution, Warning. Z.B.: "Note The Interrupt Pending bits must be carefully handled because the EIC state machine and its internal priority hardware stack could be forced to a non recoverable condition if unexpected pending bit clear operations are performed." Peter Peter Dannegger schrieb: > Ja, 35 Seiten über die Interruptlogik ist schon sehr beeindruckend. Yep, aber ich habe lieber ein paar Seiten mehr als die fehlenden Seiten bei den ARM PrimeCells. Dort ist nämlich der für's Nesting wichtige Teil dermassen konsequent unter den Tisch gefallen, dass manche sie als dafür effektiv ungeeignet abqualifizieren und wieder andere sich fragen wie das überhaupt funktionieren kann. Und einfach mal in der Doku zwischendrin darauf hinzuweisen, dass der VIC eigentlich sowieso ungeeignet für alles ist (so jedenfalls lesen manche den entsprechenden Passus) ist auch nicht wirklich lustig. Aber ARM hat aus dem Graus der vielen komplexen Interrupt-Controller der ARM7/9 den richtigen Schluss gezogen und mit dem NVIC der Cortexe klar Schiff gemacht. Ist dadurch zwar nicht so arg viel einfacher geworden (geht bei dem Thema nicht), aber einheitlich. Wirklich übersichtlich sind eigentlich nur die ARM7er von Analog Devices - die haben schlicht keinen Interrupt Controller eingebaut. Peter Dannegger schrieb: > The Interrupt Pending bits must be carefully handled because the EIC > state machine and its internal priority hardware stack could be forced > to a non recoverable condition if unexpected pending bit clear > operations are performed." Das liest sich auch nicht schlimmer als manche Bugs quer durch die Controllerwelt. NXP hat in den LPC2100/2200 einen CAN Controller drin, der dank eines Bug die halbe Funktionalität verloren hat. Der CAN Controller diverser PICs kann sich durch fast normale Busverhältnisse und Nichtstun in Nullkommanix in eine ähnliche "unrecoverable condition" manövrieren und ziemlich viele CAN Controller von Microchip reichen bei bestimmten undramatischen Busproblemen defekte Pakete als korrekt durch. So geht das endlos weiter, egal wohin man schaut. Ähm, kannn es sein, dass Ihr langsam etwas OffTopic geratet? Ja. Aber deine Frage war ja wohl beantwortet, jedenfalls hatte ich das so verstanden. War nicht bös gemeint, aber das Thema ist ja ganz interessant, dass man da fast nen eigenen Thread aufmachen könnte :-)
Gast
#1691329
Peter Dannegger schrieb: > Und es ist besser, wenige MCs richtig zu beherrschen, als viele nur > halb. > Denn nur dann kann man auch zuverlässige Programme schreiben. > Man muß sich schon eingelesen haben, wie der MC intern arbeitet, damit > man den Programmablaufplan fehlerfrei erstellen kann. Dem kann ich nur zustimmen. Und weil es gerade so schön zu dem Thema passt - eine schöne Überraschung hält der sleep-Befehl beim AVR auch noch bereit, wenn man ihn mit Timer-Interrupt und ADC-Interrupt kombiniert. Wer liest schon den unauffällig platzierten Hinweis im Datenblatt zu sleep, dass der Befehl nebenher noch eine AD-Wandlung lostritt... Zum Glück arbeite ich vorwiegend in Assembler - ich kann mir vorstellen, dass diese Falle C-Anwendern noch viel eher verschlossen bleibt. Muss aber gestehen, dass ich auch unfreiwillig darüber gestolpert bin. :-) Wo so etwas passieren kann? Wenn man mit Timer-Interrupt AD-Daten zu fixen Intervallen erfassen möchte und auch die AD-Wandlung per Interrupt erfolgt und zwecks Energeieinsparung (Datenlogger) in der untätigen Zeit sleep benutzt wird. guest schrieb: > Zum Glück arbeite ich vorwiegend in Assembler - ich kann > mir vorstellen, dass diese Falle C-Anwendern noch viel > eher verschlossen bleibt. Was hat das denn mit C vs. Assembler zu tun? Datasheet lesen muss man so oder so. Oder hältst du Assembler-Programmierer für die Elite der Zunft? Ich finde ja die Interruptlogik des 8051 genial einfach: Jede Priorität hat ein Bit, also 4 Bits bei 4 Prioritäten. Jeder pending Interrupt prüft, ob Bits gleich oder größer seiner Priorität gesetzt sind. Wenn nicht, dann setzt er das seiner Eintrittspriorität entsprechende Bit und springt seinen Vektor an. Jedes RETI löscht dann anfangend vom höchsten wieder ein Bit. Damit sind verschiedene "Schweinereien" möglich aber "non recoverable conditionen" unmöglich. Z.B. kann man eine Priorität verlassen, indem innerhalb des Interrupthandlers ein RETI ausgeführt wird. Oder man kann auch innerhalb des Interrupts die Priorität ändern, sie wird sofort nach dem nächsten Befehl gültig. Ein Interrupt kann sich damit bis zu 3-mal selbst unterbrechen. Das RETI benötigt die Kenntnis der Eintrittspriorität nicht mehr, da es ja immer nur das höchstwertigste Prioritätsbit löscht. Die ganze Interruptprioritätslogik des 8051 besteht also nur aus 4 Bits. Wow. Peter Peter Dannegger schrieb: > Die ganze Interruptprioritätslogik des 8051 besteht also nur aus 4 Bits. Ich hatte oben schon die ADUC7000 angeführt. Da sind es sogar nur 2. Und beim AVR nur ein einziges. Wow! A. K. schrieb: > beim AVR nur ein einziges. Wow! Kein "Wow!", denn das ist wirklich schade bei den Mega/Tiny-AVRs, daß die keine Prioritäten haben. Peter Peter Dannegger schrieb: > Kein "Wow!", denn das ist wirklich schade bei den Mega/Tiny-AVRs, daß > die keine Prioritäten haben. Peter, ich habe dich nur mit deinen 4 Bits auf den Arm genommen. Natürlich hast du recht.
Gast
#1691522
> Was hat das denn mit C vs. Assembler zu tun? Datasheet lesen muss man so > oder so. Oder hältst du Assembler-Programmierer für die Elite der Zunft? funktioniert doch immer wieder :-) locker bleiben! Peter Dannegger schrieb: > Ja, 35 Seiten über die Interruptlogik ist schon sehr beeindruckend. > Und dann die vielen Note, Avoid, Caution, Warning. Das fiese an dem Teil (EIC von STR7) ist so weit ich sehe, dass man am Ende des Handlers das toplevel pending bit selber rausfinden und explizit zurücksetzen muss. Und dass man da, wenn man das falsche Bit erwischt, Unfug treiben kann. Das ist ausgesprochen doof, wenn der gleiche Handler für mehrere Quellen zuständig ist - insbesondere wenn man auf ARM7 einen zentralen Wrapper für alle Interrupts verwendet, der den Verwaltungskram macht. Üblich ist eigentlich, dass der Interrupt-Controller ein eher allgemein gehaltenes "End Of Interrupt" mitgeteilt bekommt und er aufgrund seiner Zustandsinformationen selber spitz kriegt, wer gemeint ist. Peter Dannegger schrieb: > Jeder pending Interrupt prüft, ob Bits gleich oder größer seiner > Priorität gesetzt sind. Wenn nicht, dann setzt er das seiner > Eintrittspriorität entsprechende Bit und springt seinen Vektor an. > Jedes RETI löscht dann anfangend vom höchsten wieder ein Bit. Diese Beschreibung könnte auch ganz gut die Technik beiden VIC Varianten der ARM PrimeCells erklären (z.B. LPC2000). Die präzise Beschreibung der Prioritätsmechanik fehlt dort völlig, und das sorgt für Irritation. Nachteil könnte sein, dass man m.E. weder beim 8051 noch beim VIC rauskriegt, auf welchem priority level man grad läuft, weil diese Information nur als bitmap in einem nicht zugänglichen pending interrupt register steht. Generell taucht in beiden Versionen die interrupt priority nur recht sparsam auf. Ein explizites Sperren aller interrupts unter einem bestimmten priority level existiert nicht. In einfacher gestrickten Controller-Programmen spielt das kaum eine Rolle. OS-Kernels, ob grosse oder kleine (RTOS), arbeiten jedoch gerne mit solchen priority levels, gehen gerne auch mal ad hoc rauf und runter, und grad der NVIC der Cortexe kommt dieser Arbeitsweise sehr entgegen. A. K. schrieb: > Diese Beschreibung könnte auch ganz gut die Technik beiden VIC Varianten > der ARM PrimeCells erklären (z.B. LPC2000). Die präzise Beschreibung der > Prioritätsmechanik fehlt dort völlig, und das sorgt für Irritation. Ich kann jetzt auch nicht mehr sagen, wo ich das mit den Bits der Interruptlogik des 8051 gelesen hab. Es steht jedenfalls nicht in den üblichen Datasheets/Manuals. Es ist aber doch sehr wichtig, um die Funktion zu verstehen. Maxim (Dallas) hat auch einige 8051, wo diese Bits (Read only) gelesen werden können. > Nachteil könnte sein, dass man m.E. weder beim 8051 noch beim VIC > rauskriegt, auf welchem priority level man grad läuft Ich überlege gerade, wozu man das brauchen könnte. Wenn Du von einem bestimmten Vektor kommst, kannst Du aber in dessen Prioritätsbits nachschauen, dann weißt Du die gerade laufende Priorität. > Ein explizites Sperren aller interrupts > unter einem bestimmten priority level existiert nicht. Auch da weiß ich nicht, wozu man das brauchen könnte. Peter Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|