Forum: Mikrocontroller und Digitale Elektronik STM32: Interrupts vs. Events?


von Thomas B. (escamoteur)


Lesenswert?

Hi,

beim Versuch das Interruptsystem des STM32 zu verstehen, bin ich leider 
an einer Stelle etwas Ratlos?
1
Functional description
2
3
To generate the interrupt, the interrupt line should be configured and enabled. This is done
4
by programming the two trigger registers with the desired edge detection and by enabling
5
the interrupt request by writing a 1 to the corresponding bit in the interrupt mask register.
6
When the selected edge occurs on the external interrupt line, an interrupt request is
7
generated. The pending bit corresponding to the interrupt line is also set. This request is
8
reset by writing a 1 in the pending register.
9
10
To generate the event, the event line should be configured and enabled. This is done by
11
programming the two trigger registers with the desired edge detection and by enabling the
12
event request by writing a 1 to the corresponding bit in the event mask register. When the
13
selected edge occurs on the event line, an event pulse is generated. The pending bit
14
corresponding to the event line is not set


Was sind Events? In wie fern hängen sie mit den Systeminterrupts 
zusammen?

Gruß
Tom

von Rangi J. (rangi)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Thomas B. (escamoteur)


Lesenswert?

D.h. für die normale Programmierung brauche ich die Events gar nicht, da 
nehme ich einfach die Interruptregister wie gewöhnlich.

Gruß
Tom

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

SEVONPEND=1 oder SEV im Handler.

von Peter D. (peda)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Thomas B. (escamoteur)


Lesenswert?

Ähm, kannn es sein, dass Ihr langsam etwas OffTopic geratet?

von (prx) A. K. (prx)


Lesenswert?

Ja.

Aber deine Frage war ja wohl beantwortet, jedenfalls hatte ich das so 
verstanden.

von Thomas B. (escamoteur)


Lesenswert?

War nicht bös gemeint, aber das Thema ist ja ganz interessant, dass man 
da fast nen eigenen Thread aufmachen könnte :-)

von guest (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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?

von Peter D. (peda)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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!

von Peter D. (peda)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von guest (Gast)


Lesenswert?

> 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!

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

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
Noch kein Account? Hier anmelden.