Forum: Mikrocontroller und Digitale Elektronik Verschachtelte Interrupts auf ARM


von Rumkugel (Gast)


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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.

von Floh (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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?

von Rumkugel (Gast)


Lesenswert?

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ß

von Rumkugel (Gast)


Lesenswert?

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

von Maxx (Gast)


Lesenswert?

Per Software ausgelöster HW Interrupt (IF manuell setzen)? Also IRQ 
Mode?
Oder Softwareinterrupt (SWI) im SVC Mode?

Zweiteres sollte keine Probleme bereiten.

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Ebenfalls nützlich wäre die Angabe die Entwicklungsumgebung. Es gibt 
davon nämlich mehrere.

von Rumkugel (Gast)


Lesenswert?

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

von Rumkugel (Gast)


Lesenswert?

A. K. schrieb:
> Ebenfalls nützlich wäre die Angabe die Entwicklungsumgebung. Es gibt
> davon nämlich mehrere.

uvision3 von Keil

von (prx) A. K. (prx)


Lesenswert?

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.

von Rumkugel (Gast)


Lesenswert?

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ß

von Floh (Gast)


Lesenswert?

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? :-)

von Rumkugel (Gast)


Lesenswert?

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ß

von holger (Gast)


Lesenswert?

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

von Telekatz (Gast)


Lesenswert?

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();.

von Rumkugel (Gast)


Lesenswert?

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.

von holger (Gast)


Lesenswert?

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

von Floh (Gast)


Lesenswert?

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?

von A. S. (telekatz)


Lesenswert?

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.

von Rumkugel (Gast)


Lesenswert?

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

von Rumkugel (Gast)


Lesenswert?

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ß

von Peter D. (peda)


Lesenswert?

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