Hallo miteinander,
ich verzweifle gerade an den verschachtelten Interrupts meines STR91xFA.
Und zwar habe ich mir einen Softwareinterrupt gebaut der ziemlich lang
ist und von den Kommunikationsinterrupts unterbrochen werden können
soll.
Leider klappt das überhaupt nicht. Offenbar starten eine Weile lang
munter Interrupts durcheinander bevor der Controller nach ein paar
Sekunden abstürzt.
Hat jemand da Erfahrung oder eine Idee?
Es ist einigermassen schwierig, jemandem mitzuteilen, was er falsch
gemacht haben könnte, wenn derjenige völlig hinter dem Berg hält, was er
bisher überhaupt versucht hat. Anders ausgedrückt: Fehler in Zeile 42.
Allerdings hast du dir mit dem STR9 und seinen 2 kaskadierten VICs nicht
unbedingt das einfachste Übungsgelände ausgesucht.
Rumkugel schrieb:> Hat jemand da Erfahrung oder eine Idee?
Normalerweiße macht man Interrupts halt so kurz wie möglich, damit der
beschriebene Fall nicht eintreten kann.
Kannste dein Programm nicht so umbauen, dass du die Kommunikation vom
Interrupt in die main oder eine von main aufgerufene Funktion verlegst?
Dann könntest du dir den Softwareinterrupt sparen und die anderen
Interrupts könnten nach belieben auslösen.
Rumkugel schrieb:> Und zwar habe ich mir einen Softwareinterrupt gebaut der ziemlich lang> ist und von den Kommunikationsinterrupts unterbrochen werden können> soll.
Was verstehst du unter einem Softwareinterrupt?
Floh schrieb:> Kannste dein Programm nicht so umbauen, dass du die Kommunikation vom> Interrupt in die main oder eine von main aufgerufene Funktion verlegst?> Dann könntest du dir den Softwareinterrupt sparen und die anderen> Interrupts könnten nach belieben auslösen.
So läuft es bisher und das funktioniert auch.
Allerdings möchte ich nun in der main etwas zeitunkritisches Erledigen
solange keine Kapazität für die eigentliche Aufgabe benötigt wird. Die
ist jedoch wichtig und sollte regelmäßig und pünktlich ausgeführt
werden.
A. K. schrieb:> Anders ausgedrückt: Fehler in Zeile 42.
Ich würd ja Code posten und auch konkreter werden, aber es ist halt
wirklich viel. Falls mir jemand sagen kann was konkret er gern sehen
würde kann ich es natürlich posten.
Gruß
A. K. schrieb:> Was verstehst du unter einem Softwareinterrupt?
Einen Interrupt der per Software ausgelöst wird. Dadrin steht in diesem
Fall recht viel Code. Darum soll er unterbrochen werden können
Per Software ausgelöster HW Interrupt (IF manuell setzen)? Also IRQ
Mode?
Oder Softwareinterrupt (SWI) im SVC Mode?
Zweiteres sollte keine Probleme bereiten.
Rumkugel schrieb:> Ich würd ja Code posten und auch konkreter werden, aber es ist halt> wirklich viel. Falls mir jemand sagen kann was konkret er gern sehen> würde kann ich es natürlich posten.
Viel Code hilft wenig, da hast du Recht.
Aber ganz ohne Problembeschreibung nützt auch nichts. Du hast oben kaum
mehr Details vermittelt als ein allgemeines "Hilfe!" enthält.
Das fängt damit an, dass der Begriff "Softwareinterrupt" bei ARM/STR9
nicht eindeutig besetzt ist, darunter jeder etwas anderes verstehen
kann.
Das geht weiter mit dem Aufbau des Interrupt-Handlers. Verschachtelte
Interrupts sind bei ARMs etwas "speziell", weil dieser Aspekt in der
ursprünglichen Architekturdefinition schlicht vergessen wurde.
Usw.
Rumkugel schrieb:> Einen Interrupt der per Software ausgelöst wird. Dadrin steht in diesem> Fall recht viel Code. Darum soll er unterbrochen werden können
Schon wieder eine fast völlig inhaltslose Darstellung. Welcher Interrupt
oder welche Exception wird wie per Software ausgelöst?
Merke: Wenn du konkrete Antworten haben willst, dann frag konkret mit
konkreter Information im Gepäck. Sonst gibt's nur endlose Rückfragen,
allgemein gehaltene Antworten und irgendwann genervte Leser. Versuche
dich in jene Leute hineinzuversetzen, von denen du dir Antworten
erhoffst. Keiner kann deine Gedanken lesen.
Ok, ich versuche es mal so:
Ich möchte eine dicke Funktion aus meiner main in einen (von Software
ausgelösten) Interrupt packen, damit in der main noch irgendwas andres,
zeitunkritisches getan werden kann.
Das Auslösen des Interrupts funktioniert auch, wenn nicht die dicke
Funktion, sondern kurzer Code drin steht. Die dicke Funktion braucht ca.
350us, darum sind wohl verschachtelte Interrupts notwendig, damit meine
Kommunikation noch läuft.
Ich nutze eigentlich die Str9-Lib mit der man auch Prioritäten an
Interrupts verteilt, damit sie verschachtelt laufen können. Das klappt
aber nicht.
Hoffentlich habe ich damit zumindest schonmal mein Problem schildern
können
Gruß!
Rumkugel schrieb:> Hoffentlich habe ich damit zumindest schonmal mein Problem schildern> können
Nein, weiterhin nur allgemeines Geschwafel, keine konkrete Antwort auf
die sehr konkrete Frage nach dem ominösen Softwareinterrupt => ich
klinke mich hier aus, mir reicht's.
Ich versteh nicht warum der Softwareinterrupt soviel Aufsehen erzeugt.
Der funktioniert doch...
Was nicht funktioniert ist das Verschachteln der Interrupts.
also zu dem Softwareinterrupt. Er sieht so aus:
wird die dicke Funktion ausgeklammert und nur die Ausgabe wieder
reingenommen funktioniert alles einwandfrei. Sogar die dicke Funktion in
langen Abständen scheint zu gehen, aber sie soll letztendlich alle 2ms
aufgerufen werden und das läuft nicht.
tut mir leid wenn ich mich umständlich ausdrücke, aber bin halt auch
kein Experte..
Gruß
was würde das im Programmablauf ändern, anstatt hier:
Rumkugel schrieb:> VIC1->SWINTR = (1 << 15); // trigger software interrupt
das
Rumkugel schrieb:> //SerialPutString("@");> DickeFunktion();
zu schreiben?
Ich mein du triggerst irgendwo im Hauptprogramm den Softwareinterrupt,
stattdessen kannst du doch auch einfach die Funktion aufrufen.
Ergebnis:
- SW-Int raus
- HW-Int kann die Funktio unterbrechen
- keine verschachtelten Ints
Wo ist der Haken? :-)
Floh schrieb:> Wo ist der Haken? :-)
Wenn ich den Interrupt aus dem Hauptprogramm triggere ist das auch
tatsächlich kein Problem, hab ich grad erstaunt festgestellt.
Leider hab ich damit nicht was ich möchte. Der Interrupt soll dann
ausgelöst werden, wenn ein komplettes Paket über SPI empfangen wurde,
darum versuche ich die Zeile in den SPI-Interrupt zu setzten.
Nun könnte man argumentieren ich kann ja einfach eine Flag in der Main
abfragen, aber ich möchte dass der Softwareinterrupt wirklich sofort
ausgelöst wird, falls die andere Funktion in der Main auch groß ist.
Danke fürs Mitdenken und Gruß
>Der Interrupt soll dann>ausgelöst werden, wenn ein komplettes Paket über SPI empfangen wurde,>darum versuche ich die Zeile in den SPI-Interrupt zu setzten.
Dann ruf die DickeFunktion();
im SPI Interrupt auf. Wieso SoftwareInterrupt?
Rumkugel schrieb:> Ich versteh nicht warum der Softwareinterrupt soviel Aufsehen erzeugt.> Der funktioniert doch...
Weil es beim ARM Software Interrupt instruction (SWI) gibt, die zum
Wechsel in den Supervisor Mode dient gibt. Das was du machst ist ein
Hardware Interrupt, der durch setzen eines Bits in einem Register per
Software ausgelöst wird.
Die Bezeichnung Softwareinterrupt war hier nicht eindeutig. Dein
Softwareinterrupt ist ein normaler IRQ.
Pack die Interrupts, welche deinen Softwareinterrupt unterprechen
sollen, in den FIQ. Der kann einen IRQ unterbrechen. Das kann ein
anderer IRQ nicht.
Poste doch mal die DickeFunktion();.
Telekatz schrieb:> Pack die Interrupts, welche deinen Softwareinterrupt unterprechen> sollen, in den FIQ. Der kann einen IRQ unterbrechen. Das kann ein> anderer IRQ nicht.
Das ist leider ziemlich viel Kommunikation: Mehrere uarts, i2c, spi
timer usw. So wie ich das verstanden habe sollte man aber nur eine
Quelle als FIQ verwenden.
Telekatz schrieb:> Poste doch mal die DickeFunktion();
Die dürfte eigentlich nicht relevant sein. Sind halt viele arithmetische
Sachen drin: Kalman-Filterung, Regelungsalgorithmen usw. und besteht aus
zig Funktionen, ist also wirklich lang..
holger schrieb:> Dann ruf die DickeFunktion();> im SPI Interrupt auf. Wieso SoftwareInterrupt?
Der SPI-Interrupt hat eine sehr hohe Priorität und ist ziemlich kurz.
Der Softwareinterrupt soll halt eine niedrige Priorität bekommen, denn
er ist sehr lang und soll von der übrigen Kommunikation unterbrochen
werden.
>> Dann ruf die DickeFunktion();>> im SPI Interrupt auf. Wieso SoftwareInterrupt?>Der SPI-Interrupt hat eine sehr hohe Priorität und ist ziemlich kurz.>Der Softwareinterrupt soll halt eine niedrige Priorität bekommen, denn>er ist sehr lang und soll von der übrigen Kommunikation unterbrochen>werden.
Toll, und du rufst DickeFunktion(); per SWI im SPI Int auf.
Kann der SPI Int auch in DickeFunktion(); auftreten?
Dann hast du einen DeadLock. Stack läuft irgendwann über.
Rumkugel schrieb:> Die dürfte eigentlich nicht relevant sein. Sind halt viele arithmetische> Sachen drin: Kalman-Filterung, Regelungsalgorithmen usw. und besteht aus> zig Funktionen, ist also wirklich lang..
kurze Frage:
Was macht die main sonst, dass du das nicht in die main packen willst?
Rumkugel schrieb:> Das ist leider ziemlich viel Kommunikation: Mehrere uarts, i2c, spi> timer usw. So wie ich das verstanden habe sollte man aber nur eine> Quelle als FIQ verwenden.
Es gehen auch mehrere Interrupts im FIQ. Mann muss halt seinen eigenen
Handler dafür erstellen.
Rumkugel schrieb:> Der SPI-Interrupt hat eine sehr hohe Priorität und ist ziemlich kurz.> Der Softwareinterrupt soll halt eine niedrige Priorität bekommen, denn> er ist sehr lang und soll von der übrigen Kommunikation unterbrochen> werden.
Die Priorität hat nur einen Einfluss, wenn beide Quellen gleichzeitig
anstehen. Unterbrechen kann ein IRQ hoher Priorität einen IRQ mit
niederer Priorität nicht.
Du könntest versuchen, deine dicke Funktion in mehrer Teile aufzuteilen
und in eine State Machine zu packen. Nach abarbeitung eines States
beendest du den IRQ ohne das Software Interrupt flag zu löschen. Der IRQ
sollte dann nochmal zur Ausführung anstehen. Ist dann ein Interupt mit
höherer Priorität anstehend, müsste dieser zuerst ausgeführt werden.
holger schrieb:> Toll, und du rufst DickeFunktion(); per SWI im SPI Int auf.> Kann der SPI Int auch in DickeFunktion(); auftreten?> Dann hast du einen DeadLock. Stack läuft irgendwann über.
Der SPI-Interrupt kann auch während DickeFunktion() auftreten.
Allerdings wird nicht jedes Mal der SWI aufgerufen, sondern nur bei
einem kompletten Paket. Das passt auf jeden Fall.
Floh schrieb:> kurze Frage:> Was macht die main sonst, dass du das nicht in die main packen willst?
Das ist noch offen. Es soll aber auch möglich sein da sehr lange
Funktionen reinzuschreiben, so dass es nicht möglich ist laufend Flags
abzufragen
ich bin an einem wirklich seltsamen Punkt angelangt:
wenn ich den Softwareinterrupt in meiner main-Schleife auslöse,
funktioniert das Ganze auch mit der dicken Funktion im Interrupt.
Also so:
[/c]
while(1)
{
VIC1->SWINTR = (1 << 15); // trigger software interrupt
}
[c]
Im Interrupt selbst wird zuerst ein Flag abgefragt, darum kann man das
auch ruhig spammen.
Setz ich dieselbe Zeile aber in irgendeinen anderen Interrupt, kommt nur
noch Gemüse.
Das muss doch also recht leicht zu lösen sein, oder?
Sollte ich irgendwo ein bestimmtes Register beschreiben?
Gruß
Ein SW-Interrupt ist nur ein verkappter Unterfunktionsaufruf.
Er kann daher so lang sein, wie Du willst.
Und er kann daher auch Argumente erhalten und Returnwerte zurückgeben,
für echte Interrupts ein Ding der Unmöglichkeit.
Ein HW-Interrupt dagegen soll so kurz wie möglich sein und keine
Unterfunktionen aufrufen, also auch keine SW-Interrupts.
Ganz häßlich wirds, wenn der HW-Interrupt nen SW-Interrupt aufruft und
dieser wieder auf einen HW-Interrupt wartet, ergibt dann einen Deadlock.
Außerdem ergibt eine Unterfunktion in Interrupts die Gefahr, daß 2
Instanzen davon laufen.
Kannst ja mal im Main und im Interrupt auf die UART oder ein LCD
zugreifen, das ergibt dann ein lustiges Text-Kuddelmuddel.
Peter