Forum: Mikrocontroller und Digitale Elektronik ARM Nested Interrupts mit Keil µVision mit RealView?


von Dietmar (Gast)


Angehängte Dateien:

Lesenswert?

Hallo ARM-Gemeinde,

im Laufe der Woche gab es im Thread

Beitrag "Interrupts"

eine Frage zum Compiler-Umstieg bei Keil von komfortablen CARM (der im
Dezember 2005 von Keil eingestellt wurde) auf RealView für ARM (der neue
bei Keil, von ARM übernommen, Keil hat sich Ende 2005 bei ARM eingekauft
bzw. wurde von ARM gekauft), der ab diesem Zeitpunkt unter Keil µVision
verwendet wird.

Dort hatte ich eine Lösung gepostet, wie man die
Nested-Interrupt-Technik unter RealView weiterhin anwenden kann, da
unter RealView die Inline-Assembler-Makros aus den bekannten
Hitex-Examples zum Umschalten nicht mehr funktionieren. RealView
verhindert zuverlässig den Zugriff auf die dafür wichtigen Register R13
(SP), R14 (LR) und R15 (PC) aus C-Sourcefiles, auch unter
Inline-Assembler. Unter RealView geht sowas nur noch in reiner
Assemblerprogrammierung in so genanntem Embedded Assembler. Aber, das
ist nicht mehr das Problem, da gelöst.

Diese Sache betrifft also nach wie vor anscheinend nicht nur mich, der
bereits ein Software-Projekt in tagelanger Arbeit von CARM nach RealView
umgebaut hat.

Bis heute habe ich im Internet keine Ersatzlösung für die Makros
gefunden, und bin nach einigen Überlegungen darauf gekommen, diese
letztendlich in Assembler selbst zu schreiben. Dazu habe ich die Makros
genommen und sie zu Funktionen umgebaut, die natürlich nicht mehr ganz
so komfortabel sind wie die Makros, da sie zwangsläufig etwas mehr Code
und Laufzeit haben (Funktionsaufruf, zusätzliche Verwendung und
Sicherung eines Registers, denn die Returnadresse der Funktionen muß
über die Prozessor-Mode-Umschaltung hinweg erhalten bleiben).

Das Assembler-File ist hier direkt downloadbar und in die µVision
einbindbar, damit die Funktionen aus einem Interrupt heraus sofort
aufrufbar. Eingesetzt in das Nested Interrupt Example von Hitex,
funktioniert das auf meinem Keil-Demo-Board MCB2100 wunderbar.

Wer möchte mit mir mal verifizieren, ob das alles so in Ordnung ist?
Und, wie weit arbeitet der VIC-Controller in den LPC21xx und LPC22xx
(PL190 von ARM) mit Nested Interrupts zusammen?

Hat mal jemand einen Interrupt-Prioritäts-Handler in Software
geschrieben, der verschiedene Interrupt-Prioritäts-Ebenen behandeln
kann, wie sie in anderen Mikrocontrollern als Hardware (z.B. 80C515,
80C517, C166) implementiert sind?

Wenn nicht, weiß noch jemand ein gutes ARM-Forum auch für ARM7, außer
'YAHOO LPC2000' oder 'Keil'?

Gruß

Dietmar

von Dietmar (Gast)


Lesenswert?

@Webmaster:

Um einen Thread im ARM-Forum zu eröffnen, bedarf es wohl einiger 
schwerer Klimmzüge. Da landet so vieles nicht, oder mit anderen Worten, 
verschwindet vieles, was für die ARM-User interessant wäre. So bin ich 
auch erst nach 3 Fehlversuchen mit meinem Thread im ARM-Forum gelandet, 
in dem ich zufällig mal mit ARM-sensitiven Worten im Betreff herum 
gespielt habe.

Wie kommt man auf solche Idee? Nach einigen Überlegungen: Reiner Zufall!

Wie kann ich ahnen, daß im "Betreff" irgend ein (und dann auch noch 
welcher???) ARM-spezifischer Ausdruck vorkommen muß?

Der Thread von Wolfgang ("Interrupt") mit der Nested Interrupt Technik, 
der für die ARM-User enorm wichtig sein kann, ist im allgemeinen Forum 
mittlerweile auf Seite 5 "versackt". Das interessiert dort kein Schwein 
mehr.

Möglicherweise hatte der, ebenso wie ich, auch versucht, seinen Thread 
im ARM-Forum zu posten.

Hier gibt es sicher noch Verbesserungs-Potential. Z.B., daß, wenn man 
aus dem ARM-Forum "Neuer Beitrag" anklickt, man denn auch dort an der 
richtigen Stelle postet.

Gruß

Dietmar

von mthomas (Gast)


Lesenswert?

- Was mit "ARM-Forum" gemeint ist, ist mir immer noch nicht klar.
- Im Forum gehen Beiträge realtiv schnell unter, zur Wissenssammlung 
bietet sich das Wiki ("Aritkel") an.
- weitere Foren: en.mikrocontroller.net, devkitarm-users, gnuarm 
yahoo-Gruppe, Codesourcery.

Was ist bei den von NXP für LPC23xx/24xx und LPC213x/4x bereitgestellten 
Beispielen falsch/unzulänglich, in denen die Verwendung von 
interrupt-nesting mit dem RealView compiler demonstriert wird? Ich habe 
den Code zwar nicht selbst ausprobiert, sondern nur als Vorlage für 
gcc-Portierungen genutzt, aber entsprechende Makros in inline-Assembler 
für RV ähnlich denen bei einigen älterne CKARM Beispielen sind dort 
enthalten inkl. ein wenig erläuterndem Kommentar zum Unterscheid 
CKARM/RV.
Das eigentliche "Nesting" hat meines Wissens nichts mit dem 
Interrupt-Controller direkt zu tun, sondern mit der Funktionalität des 
Cores. Verwaltung der Prioritäten ist meines Wissens Aufgabe des 
Interrupt-Controllers (VIC 190/192, AIC etc.).
Bin selbst dazu übergegangen, für die allermeisten ARM Entwicklungen 
einen Assembler-Wrapper für IRQ-Exceptions zu nutzen, bei dem immer 
"genestet" wird. Die Vorgehensweise spart einiges an Bastelei beim 
Portieren von Code (keine herstellerspezifischen Erweiterungen wie 
__irq, inline-assembler etc. im C-Quellcode), verschwendet allerdings 
ein paar Zyklen, da der Wrapper immer genutzt wird, auch dann wenn man 
nesting nicht braucht. Zur Not bleibt für kritische Interrupts noch 
"FIQ".

Martin Thomas

von Peter D. (peda)


Lesenswert?

Nested Interrupts sind ja schon aufm AVR sauschwer und gefährlich.

Du hast Doch 2 Interruptprioritäten, damit sollte man meist auskommen.

Oder nimm nen 8051, der hat 4 :)

Die ARM7 von ST haben 17 Interruptprioritäten, das sollte ja dicke 
reichen.
Die 35 Seiten dazu im Datasheet sehen allerdings auch nicht gerade 
einfach aus.


Peter


P.S.:
Die einzige sichere Methode für Interruptprioritäten auf dem AVR, die 
ich gefunden hab, ist einen Timerinterrupt dazu zu mißbrauchen.
Der arbeitet dann quasi als Scheduler aller niederpriorisierter 
Interruptquellen. Und er stopt sich zuerst selbst, damit er sich nicht 
selber unterbrechen kann.

von Dietmar (Gast)


Lesenswert?

@mthomas:

>- Was mit "ARM-Forum" gemeint ist, ist mir immer noch nicht klar.

Na, hier, die Abteilung, wo wir uns gerade befinden, in der sich nur 
ARM-spezifische Themen befinden. Es wird ja nach ARM, 8051, PIC, usw. 
sondiert. Da kann man anscheinend nur dann einen Thread eröffnen, wenn 
im Betreff ein ARM-sensitives Wort vorkommt. Z.B. "ARM und_das_Thema", 
siehe Betreff dieses Threads. Nach Betreff, landet der Thread dann dort, 
wo er hin gehört, nämlich hier. Eine andere Auswahl habe ich nicht 
gefunden.

>Was ist bei den von NXP für LPC23xx/24xx und LPC213x/4x bereitgestellten
>Beispielen falsch/unzulänglich, in denen die Verwendung von
>interrupt-nesting mit dem RealView compiler demonstriert wird?

Ist das jetzt dein Ernst?

>mit dem RealView compiler ???

Dem widerspreche ich jetzt: Die Beispiele (Assembler-Inline-Makros) 
stammen noch aus der Zeit vor RealView, und funktionieren unter RealView 
eben nicht mehr.

Sorry, nach LPC23xx/24xx habe ich noch nicht gesucht, da ich damit 
nichts zu tun habe.

Wenn es da neue Beispiele für RealView gibt: Wo finde ich denn die? Die 
alten Beispiele (Makros aus 4 Zeilen) kenne ich hinlänglich, siehe meine 
Beschreibung oben.

Aus dem RealView Compiler Manual geht eindeutig hervor, daß der Zugriff 
auf bestimmte Register aus C-Sourcen nicht mehr funktioniert. Und die 
Makros funktionieren tatsächlich nicht mehr. Der Compiler macht keine 
Fehlermeldung an der Stelle, er macht einfach nichts.

Darum, meine Frage, und den Aufwand, neue Embedded Assembler Funktionen 
zu schreiben (die weiter oben downloadbar sind).

Gruß

Dietmar

von ARM-Fan (Gast)


Lesenswert?

>Na, hier, die Abteilung, wo wir uns gerade befinden...

Was du meinst, ist nur ein Filter für die Betreffzeile,
der auf bestimmte Keywords anspricht. Guck doch mal oben
rechts das Suchfeld an...

von Dietmar (Gast)


Lesenswert?

@Peter:

>Nested Interrupts sind ja schon aufm AVR sauschwer und gefährlich.

AVR, das ist doch gar kein ARM, noch nicht mal ähnlich, oder?

Natürlich weiß ich, was ich tue. Immerhin, ist "Nested Interrupt" in der 
ARM-Familie ein etablierter Begriff. Es sollte damit möglich sein, sich 
jede erdenkliche Interrupt-Konfiguration, wenn man sie denn braucht, in 
Software selbst zu schreiben. Das ist die Grund-Idee, ist flexibler als 
eine fest eingegossene Hardware-Interrupt-Logik (wenn möglicherweise 
auch etwas langsamer).

>Die ARM7 von ST haben 17 Interruptprioritäten...

Nee, das ist ja eine völlig andere Familie, obwohl ARM. Ein Umstieg von 
LPC zu ST ist wiederum ebenso aufwändig wie der Umstieg von 8051 zu LPC, 
wegen der völlig verschiedenen Peripherie. Die einzige Gemeinsamkeit ist 
nur die core-nahe Programmierung, wie eben die Nested Interrupts.

Wir haben uns auf LPC festgelegt, weil die zuerst da waren und auch eine 
höhere CPU-Frequenz boten.

Der 8051 ist auch keine Lösung, da wir aus Performance-Gründen von 
dieser Familie auf ARM umgestiegen sind. Die Interrupt-Verarbeitung 
funktioniert ja auch sehr gut auf 2 Prioritätsleveln, damit kommen wir 
aus.

Über ARM und 8051 zu diskutieren ist müßig: Ein SiLabs 8051 mit 100 MHz 
konnte dem ARM mit 60 MHz bei weitem nicht das Wasser reichen: Es ist 
nicht nur der 8-Bit- zu 32-Bit- Vergleich, auch der ARM-Befehlssatz ist 
zu mächtig.

Ich überlege gelegentlich nur nach verbesserten Lösungen, das ist alles, 
die festgelegte Abarbeitungsreihenfolge des VIC-Controllers nochmals zu 
beeinflussen, ohne während der Laufzeit z.B. ständig den VIC-Controller 
neu programmieren zu müssen. Sowas sollte man ohnehin unterlassen, da 
Verlust an Überblick. Man möchte womöglich einen FIQ ersetzen, ihn mit 
der Nested Interrupt Technik auch als IRQ mit maximaler Priorität 
konfigurieren, der immer andere IRQ durchbricht, was ja normalerweise 
nicht geht.

Gruß

Dietmar

von Dietmar (Gast)


Lesenswert?

@ARM-Fan:

Welches Suchfeld?

Was soll mir das jetzt bedeuten?

Gruß

Dietmar

von Andreas K. (a-k)


Lesenswert?

Es gibt zwei recht verschiedene Ansätze, Interrupt-Routinen in ARM zu 
implementieren.

Der hier zunächst beschrieben Ansatz verwendet hoch compilerspezifische 
Makros (oder eben Aufrufe) vorne+hinten in der Routine selbst, 
Assembler-Einsprengsel, Registerzugriffe, was immer dazu nötig ist. Mal 
mit, mal ohne Compiler-Support für Interrupt-Routinen (GCC hat das zwar, 
aber verbugt, und natürlich ohne Nesting). Was Performance angeht ist 
das optimal. Was Flexibilität und Portabilität angeht eher nicht.

Ich bevorzuge die andere, schon von mthomas skizzierte Variante. Einen 
zentralen Assembler-Handler für Interrupts, der insbesondere auch für's 
Nesting sorgt, seinerseits den Vektor abholt, die Funktion aufruft und 
den/die IRQ-Controller anschliessend freigibt. Vorteile hier: Nesting 
ist problemlos, der Interrupt-Handler ist eine ganz normale Funktion 
ohne Sonderbehandlung und es darf insbesondere auch Thumb-Code sein. Das 
pflege ich dann auch so zu implementieren, dass es einem 
Interrupt-Handler egal ist, ob er vektorisiert und unvektorisiert 
aufgerufen wird (LPC2000-Problem mit 32 Quellen aber nur 16 Vektoren).

Was das Nesting von LPC2000 angeht: Ich habe das auf LPC21xx ausprobiert 
und kein Problem dabei gefunden. Die vom VIC implementierten Prioritäten 
funktionierten tatsächlich wie sie sollten, obwohl die Doku sowohl von 
ARM als auch von NXP in dieser Hinsicht eher Quell von Irritation als 
von Information ist.

von Andreas K. (a-k)


Lesenswert?

> Das eigentliche "Nesting" hat meines Wissens nichts mit dem
> Interrupt-Controller direkt zu tun, sondern mit der Funktionalität des
> Cores.

Ein bischen hängt das insofern zusammen, als Nesting nur dann wirklich 
Sinn ergibt, wenn der Interrupt-Controller sauber mit Prioritäten 
umgehen kann. D.h. wenn gesichert ist, dass in jeder Phase der 
Interrupts nur höher priorisierte als der laufende Interrupt 
durchkommen.

von Dietmar (Gast)


Lesenswert?

@mthomas, Andreas Kaiser:

Danke für eure ausführlichen Antworten, die mir erst mal eine Menge 
neuer Anregungen verschaffen. Damit ist das Thema noch lange nicht vom 
Tisch: ARM-Assembler-Programmierung, ja, OK, damit sollten wir laut 
Compiler-Hersteller eigentlich vollständig verschont bleiben. Da dies 
aber Wunschdenken ist, habe ich schon erfolgreich z.B. 
FIQ-Surprise-Handler geschrieben, sowas sollte also gehen.

Was ist eigentlich ein Assembler-Wrapper? Ein neuer Ausdruck für 
"Handler"?

Ich werde einige Überlegungen anstellen müssen, mich bei nächster 
Gelegenheit wieder äußern, und sicher weitere Fragen haben.

Gruß

Dietmar

von Andreas K. (a-k)


Lesenswert?

> Was ist eigentlich ein Assembler-Wrapper? Ein neuer Ausdruck für
> "Handler"?

Wrapper = Verpackung. Hier gemeint:

ARM-IRQ-Vektor => direkt zu ASM-Code ohne VIC-Vektor, dort:
- switch to system stack
- save volatile registers
- call VIC vector (application IRQ handler)
- restore registers
- acknowledge VIC
- switch back to IRQ stack
- return from interrupt

D.h. der ganze hässliche Teil steckt im ASM Teil. Der ganze Firlefanz 
mit Stacks und Registern ist dort, der IRQ-Handler der Anwendung ist 
eine blitzsaubere C-Funktion. Steckt bei mir im startup.S drin.

von Andreas K. (a-k)


Lesenswert?

Zum Begriff "Verpackung": Eine normale C Funktion wird vom zentralen 
ASM-Code so verpackt, dass sie als IRQ-Handler dienen kann.

von Dietmar (Gast)


Lesenswert?

@Andreas Kaiser:

Danke für die ausführlichen Hinweise und Auflistung der Schritte für die 
Vorgehensweise.

Mit ARM-Assembler habe ich mich schon angefreundet, z.B. um den 
Startup-Code zu erweitern, und für spezielle Zwecke, wie 
Surprise-Interrupt-Handler mit Zähler, ist das auch notwendig.

Eine andere Frage wäre noch an mthomas:

>Bin selbst dazu übergegangen, für die allermeisten ARM Entwicklungen
>einen Assembler-Wrapper für IRQ-Exceptions zu nutzen, bei dem immer
>"genestet" wird.

"Immer genested" wie kann ich das verstehen?

Gruß

Dietmar

von Andreas K. (a-k)


Lesenswert?

> wie Surprise-Interrupt-Handler mit Zähler, ist das auch notwendig.

Du meinst wahrscheinlich den spurious interrupt handler. Wird gern 
verwechselt. Der surprise interrupt ist derjenige, der trotz scheinbar 
abgeschalteter interrupts läuft.

> "Immer genested" wie kann ich das verstehen?

Vermutlich genau das was ich auch schrieb. Dass nicht jeder einzelne IRQ 
handler entscheidet, ob er nesting zulassen will, sondern dies zentral 
und damit bei jedem IRQ geschieht.

von Dietmar (Gast)


Lesenswert?

>> wie Surprise-Interrupt-Handler mit Zähler, ist das auch notwendig.

>Du meinst wahrscheinlich den spurious interrupt handler. Wird gern
>verwechselt. Der surprise interrupt ist derjenige, der trotz scheinbar
>abgeschalteter interrupts läuft.

Nein nein, das war schon ganz richtig gemeint.

Gruß

Dietmar

von Andreas K. (a-k)


Lesenswert?

Dietmar wrote:

> Nein nein, das war schon ganz richtig gemeint.

Hmm. Es aber eigentlich weder einen Surprise-Interrupt-Handler noch 
einen -Vektor. Es gibt unter dieser Bezeichnung nur ganz normale 
Interrupts vielerlei Quellen und Vektoren, die in überraschendem Kontext 
(bei eigentlich abgeschalteten Interrupt) aufgerufen werden.

von Dietmar (Gast)


Lesenswert?

>Andreas:

Ich sehe schon, Unterschied Spurious- und Surprise- Interrupt, da gibt 
es wohl noch Klärungsbedarf.

In einem anderen Thread, hab ich mich kürzlich zu einem nicht 
dokumentierten Watchdog-Problem bei den LPC2100/2200 geäußert:

Beitrag "ARM  Keil  Realview: Critical Section"

In der YAHOO "LPC2000"-Group gab es in der Vergangenheit heftige 
Diskussionen zu Spurious Interrupts und Surprise Interrupts in 
Verbindung mit Nested Interrupts, aber am Ende auch keine klare Lösung. 
Da harmoniert so manches nicht miteinander.

>Der surprise interrupt ist derjenige, der trotz scheinbar
>abgeschalteter interrupts läuft.

Genau so ist es, nach wie vor!

>Hmm. Es aber eigentlich weder einen Surprise-Interrupt-Handler noch
>einen -Vektor.

Der Default-Interrupt-Vektor, muß immer installiert sein, wenn auch als 
leere Funktion, alleine nur wegen der Spurious Interrupts, damit das 
Programm in so einem Fall nicht abstürzt. Mehr muß man dazu zunächst 
nicht wissen, es bedarf auch keiner besonderen Behandlung, denn der zum 
Spurious Interrupt gehörende echte Interrupt kommt im zweiten Anlauf 
sowieso wieder, und dann korrekt, wie er soll. Es geht nichts verloren. 
Im übrigen konnte ich in meiner Anwendung niemals einen Spurious 
Interrupt mehr beobachten, wahrscheinlich aus dem Grunde, daß der 
Vectored Interrupt Controller (ARM PL190) in den LPC-Bausteinen doch 
sehr schnell geworden ist und die Vektor-Adresse "immer" zum richtigen 
Zeitpunkt liefern kann.

Natürlich gibt es keinen Surprise-Interrupt-Handler, ich hab das mal so 
genannt, Handler, Wrapper, wie auch immer, da muß man jedenfalls selbst 
was in Assembler schreiben, wie im User Manual unter dem Kapitel 
"Spurious Interrupts" ebenfalls grob umrissen. Und es so platzieren und 
verwenden, wie man glaubt, daß es richtig sein wird.

In der Startup.s direkt an den Interrupt-Vektoren habe ich also ein 
Stück Code platziert, der den Interrupt sofort wieder zurückweisen kann, 
oder auch nicht, und zwar je am IRQ-Vektor und am FIQ-Vektor. Diesen 
habe ich mit dem Configuration Wizard in der Keil µVision Oberfläche 
schaltbar gemacht, ähnlich Präprozessor-Defines. Oder man regelt das 
über die EQUate-Anweisungen, wenn kein Configuration Wizard vorhanden 
ist. So kann ich über den Configuration Wizard mit Aktivierung oder 
Deaktivierung bestimmen, wie Surprise Interrupts behandelt werden, und 
zwar ob ein Interrupt nach der Sperrung, wenn er auftritt, noch 
bearbeitet wird, oder später. Das ist wichtig für kritische Sequenzen, 
z.B. Watchdog Feed, wenn parallel dazu auch ein langwieriger FIQ seine 
Aufmerksamkeit fordert, der wiederum kritisch für die Nachladezeit des 
Watchdog werden kann.

Surprise-Interrupt-Handler mit Zähler, ich wollte hauptsächlich mal 
wissen, wie viele Surprise-Interrupts im Schnitt in meiner Anwendung 
stattfinden, wenn ich FIQ über ARM-Core sperre, anstatt über den 
VIC-Controller.

Funktionieren, tut das alles exzellent.

Ich muß es nur zur Compile-Time schon bestimmen. Anderen Lösungen, um 
das Verhalten (FIQ Zulassung oder Zurückweisung) während der Laufzeit zu 
bestimmen, z.B. nach Wert einer Variablen entscheiden, steht aber auch 
nichts im Wege, kostet aber mehr Laufzeit wegen Zugriff auf die 
Variable.

Wenn man seine Anwendung im USER Mode laufen läßt, und nicht im SYSTEM 
Mode, wie auch von ARM vorgeschlagen, kann man auf ein 
IRQ-Surprise-Handling verzichten, da niemals Surprise-IRQ auftreten 
werden, weil IRQ nie gesperrt werden (können, weil es keinen Sinn 
macht), sondern nur FIQ, wenn FIQ verwendet.

Der Konfigurationsmöglichkeiten gibt es eben viele!

So kompliziert ist das doch nicht!

@mthomas:

Habe bei Keil tatsächlich ein neueres Beispiel für Interrupt Nesting mit 
RealView gefunden. Das hat aber auch einen beachtlichen Stack-Verbrauch, 
wogegen mein eigenes genanntes (und bisher leider nicht kommentiertes) 
Beispiel sicher nicht schlecht sein wird!

Gruß

Dietmar

von Andreas K. (a-k)


Lesenswert?

> In der YAHOO "LPC2000"-Group gab es in der Vergangenheit heftige
> Diskussionen zu Spurious Interrupts und Surprise Interrupts in
> Verbindung mit Nested Interrupts, aber am Ende auch keine klare Lösung.

Ist mir nicht entgangen. Wir hatten das Thema schon früher (als A.K.).

> Im übrigen konnte ich in meiner Anwendung niemals einen Spurious
> Interrupt mehr beobachten, wahrscheinlich aus dem Grunde, daß der
> Vectored Interrupt Controller (ARM PL190) in den LPC-Bausteinen doch
> sehr schnell geworden ist und die Vektor-Adresse "immer" zum richtigen
> Zeitpunkt liefern kann.

Wenn man nicht grad wie der STR9 mit kaskadierten VICs arbeitet, dann 
hat das weniger mit langsamerem oder schnellerem Timing zu tun, als 
vielmehr mit dem Programm selbst. Spurious Interrupts entstehen nach 
meinem Verständnis vorzugsweise dann, wenn man dem VIC hintenrum den 
Request klaut, beispielsweise indem man einen schon anstehenden 
UART-Interrupt durch einen UART-Zugriff abwürgt. In diesem Fall entsteht 
ein Fenster in dem der Prozessor bereits auf den IRQ reagiert hat, der 
VIC aber keinen Vektor mehr liefern kann.

Da der Interrupt-Controller nicht Bestandteil des ARM-Cores ist, wird 
der Zeitpunkt an dem der Core auf den IRQ reagiert und der Zeitpunkt, an 
dem der Vektor festgelegt wird, stets differieren und solange der 
separate Interrupt-Controller seinen Zustand nicht spätestens mit der 
Reaktion des Cores auf den IRQ einfriert, solange besteht dieses 
Fenster.

Das gilt übrigens prinzipbedingt für alle Architekturen mit dieser 
Arbeitsabfolge.

> Natürlich gibt es keinen Surprise-Interrupt-Handler, ich hab das mal so
> genannt, Handler, Wrapper, wie auch immer, da muß man jedenfalls selbst
> was in Assembler schreiben, wie im User Manual unter dem Kapitel
> "Spurious Interrupts" ebenfalls grob umrissen. Und es so platzieren und
> verwenden, wie man glaubt, daß es richtig sein wird.

Man kann sie auch schlicht und einfach vermeiden. Werden IRQs und FIQs 
grundsätzlich nie mit einem Befehl gleichzeitig sondern in definierter 
Reihenfolge abgeschaltet, dann entsteht das Problem erst garnicht und 
man muss in Handler nicht darauf Rücksicht nehmen.

> Wenn man seine Anwendung im USER Mode laufen läßt, und nicht im SYSTEM
> Mode, wie auch von ARM vorgeschlagen, kann man auf ein
> IRQ-Surprise-Handling verzichten, da niemals Surprise-IRQ auftreten
> werden, weil IRQ nie gesperrt werden (können, weil es keinen Sinn
> macht), sondern nur FIQ, wenn FIQ verwendet.

Das hat freilich weniger mit USER/SYSTEM als vielmehr mit konsequenter 
Programmierung zu tun. Indem man für Enable/Disable schlicht zentrale 
Funktionen verwendet. Ob man das mit Syscalls oder normalen Funktionen 
macht, ist auf Controllern ohne grösserem Betriebssystem irrelevant.

von Dietmar (Gast)


Lesenswert?

Das mag ja vielleicht alles stimmen, und den UART habe ich nie 
verwendet, mit seinen Problemen, wenn man hinten herum einen Request 
klaut (was immer das bedeuten mag).

Ja, ich hätte den LPC auch einen kaskadierten VIC mit 32 vektorisierten 
IRQ gewünscht, aber die wollten wohl sparen.

Ansonsten macht da aber auch nichts mehr Probleme.

Das Watchdog-Problem jedenfalls habe ich anhand vieler 
Konfigurationsmöglichkeiten selbst gelöst. In keinem Papier steht 
geschrieben, daß die Watchdog Feed Sequenz nicht von Interrupts 
durchbrochen werden darf. Das muß man erst mal selbst herausfinden, wenn 
man ständig Watchdog-Resets aufläuft.

Mit meiner Anwendung folge ich dem Vorschlag von ARM, die Anwendung 
vorzugsweise im User Mode zu betreiben und nicht im System Mode. Warum 
schlagen die denn das vor???

Gegen IRQ geschützte Funktionen habe ich als SWI konfiguriert. Und wenn 
nötig, sperre ich darin FIQ.

Das funktioniert alles ausgezeichnet.

Gruß

Dietmar

von Dietmar (Gast)


Lesenswert?

@Andreas:

Ein Kollege, der den ARM nur für den UART verwendete, hatte tatsächlich 
das beschriebene Problem. Aber auch dort gibt es Workarounds, das ist 
gelöst.

Nein, ich wollte ja den vergangenen Krempel (von Ende 2005 ???) auch 
nicht noch mal von vorne diskutieren.

Nichtsdestotrotz, ist bei der Diskussion ja immerhin noch die Idee 
herausgesprungen, daß ich das Auftreten von Surprise-Interrupts auch 
während der Laufzeit beeinflussen kann. Nein, ich möchte die nicht 
einfach nur eliminieren, sondern mal zulassen und mal abweisen. Und das 
funktioniert vorzüglich.

Spurious Interrupts hin, ...

Surprise Interrupts her, ...

... eigentlich war meine ursprüngliche Frage ja, ob meine Lösung zu den 
Nested Interrupts eine brauchbare ist. Dazu gibt es bis jetzt leider 
immer noch kein Statement.

Aus dem neuen Beispiel für RealView zu schließen, wäre meine oben 
gepostete Lösung sicher auch noch einen Gedanken wert, da auch getestet 
und funktionell.

Sorry, ich durchsuche das Internet gelegentlich mal nach Beispielen, 
aber nicht gerade regelmäßig (wegen des neuen Beispiels für RealView). 
Je besser der ARM läuft, desto weniger recherchiere ich. Das muß ich 
wohl mal überdenken. Ansonsten, muß ich ja zwischendurch auch mal 
arbeiten:-)

Gruß

Dietmar

von Andreas K. (a-k)


Lesenswert?

> ... eigentlich war meine ursprüngliche Frage ja, ob meine Lösung zu den
> Nested Interrupts eine brauchbare ist. Dazu gibt es bis jetzt leider
> immer noch kein Statement.

Dazu kann ich mangels Keil und RealView auch keine konkrete Aussage 
treffen. Ich könnte mir vorstellen, dass GCC unter den Teilnehmern des 
Forums etwas verbreiteter ist.

Grundsätzlich sehen die nested_... Dinger zwar in sich ok aus, nur hat 
ein stack switch innerhalb einer Funktion gewisse Nebeneffekte für die 
Funktion selbst. Einen korrekten stack frame gibt es so nicht, also muss 
man genau aufpassen, dass auch keiner erforderlich ist (lokale Variablen 
betreffend). Am sichersten geht das, indem man dort nicht viel macht als 
eine weitere (normale) Funktion aufzurufen, die den eigentlichen Job 
erledigt. Oder man kontrolliert im erzeugten Code genau, dass nichts 
unpassendes geschieht.

Und das ist ein Grund, weshalb ich, wie beschrieben, das Problem auf 
andere Weise angehe (wie auch mthomas), bei der interrupt handler ganz 
normale Funktionen sind. So nebenbei erspare ich mir dadurch auch 
diesbezügliche Bugs im GCC und muss nicht krampfhaft ARM- und Thumb-Code 
auseinanderdividieren.

von Andreas K. (a-k)


Lesenswert?

Kleiner Exkurs: AvrX verwendet für die top level functions von threads 
Funktion ohne korrekten Frame (naked). Was auch sauber dokumentiert ist. 
Wenn man also lokale Variablen auf dem Stack braucht, kann man das nicht 
im top level machen sondern muss das in eine aufgerufene Funktion 
auslagern.

Soweit ok. Kann man mit leben, wenn man genau aufpasst. Wirklich ganz 
genau aufpasst. Und immer mal kontrolliert. Denn zum Problem wurde das 
dann doch, mehrfach, weil GCC, dem das sinnlos vorkam, mir eine Nase 
drehte und solche Funktionen schlicht wieder eingliederte (inlining). 
Und das ist genau die Sorte Ärger, die ich gern vorneweg vermeide.

von Martin (Gast)


Lesenswert?

Hallo Dietmar!

Ich weiß, dein Beitrag ist schon etwas älter, aber ich habe dein 
Nested_irq.s - File eingebaut und es funktioniert hervorragend. 
Dankeschön.

Ein paar Fragen habe ich jedoch noch:
So wie aus meinen Tests hervorgeht, kann nur ein IRQ höherer Priorität 
eine gerade laufende IRQ-Routine unterbrechen.

Sagen wir der Timer 0 hat den Vektor 2, und in der IRQ-Routine wird nach 
dem Löschen des IRQs die Funktion:  nested_irq_enable();
aufgerufen, dann ist die Routine nur dann unterbrechbar, wenn ein IRQ 
vom Vektor 0 oder 1 während dieser Zeit aktiv wird. Wird ein IRQ z.B. 
mit Vektor 3 oder 4 während dieser Zeit aktiv, dann können diese IRQs, 
die laufende Vektor 2 Routine nicht unterbrechen.

Warum ist das so? Ich dachte, nach aufruf von nested_irq_enable(); sind 
grundsätzlich alle IRQs wieder freigegeben.

Danke für eure Antworten. Tschüss
Schönen Feiertag

Martin

von Jens S. (Gast)


Lesenswert?

Auch wenn der Thread schon ewigkeiten her ist, vielleicht kann mir 
jemand das ja beantworten:

Ist dieser Nested Interrupt Code auch für ein AT91SAM7X256 brauchbar?

Die Variante, dass die Prioritäten mit kontrolliert werden und nur 
Interrupts mit höherer Priorität den anderen Interrupt unterbrechen 
können klingt interessant.

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.