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.
Ebenfalls nützlich wäre die Angabe die Entwicklungsumgebung. Es gibt davon nämlich mehrere.
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ß!
A. K. schrieb: > Ebenfalls nützlich wäre die Angabe die Entwicklungsumgebung. Es gibt > davon nämlich mehrere. uvision3 von Keil
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:
1 | void SW_IRQHandler(void) |
2 | {
|
3 | // clear software interrupt
|
4 | VIC1->SWINTCR |= (1 << 15); |
5 | |
6 | //SerialPutString("@");
|
7 | DickeFunktion(); |
8 | |
9 | // write any value to VIC1 VAR
|
10 | VIC1->VAR = 0xFF; |
11 | }
|
und wird hiermit aufgerufen:
1 | VIC1->SWINTR = (1 << 15); // trigger software interrupt |
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.