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
@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
- 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
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.
@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
>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...
@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
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.
> 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.
@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
> 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.
@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
> 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.
>> 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
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.
>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
> 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.
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
@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
> ... 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.
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.
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
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.