Bascom Unterbricht ein Interrupt den Andern?

schadeng

Neues Mitglied
12. Mai 2012
14
0
1
45
Sprachen
Hallo :)

Das Hauptprogramm in Do...Loop wird ja von einem Interrupt unterbochen - klar. Was passiert aber, wenn während der Bearbeitung dieser Interrupt-Routine ein anderer Interrupt (sagen wir von einem zweiten Timer) ausgelöst wird? Wird dann der erste Interrupt unterbrochen oder wird dieser zuerst abgearbeitet und dann springt das Programm in die zweite Interrupt-Routine?

Grüße
Oliver
 
Hallo Oliver!

Bei AVR ist es so, dass alle Interrupts in einer Ebene laufen. Wenn eine Interrupt-Serviceroutine gerade abgearbeitet wird, wird diese nicht durch eine andere Interruptroutine unterbrochen, es sei denn, du setzt in der ISR das Flag I des Registers SREG (Global Interrupt Enable) zum Beispiel mit sei();.

Gruß,
Dirk
 
Hallo,

aus dem Grund sollte man die InterruptServiceRoutinen auch möglichst kurz halten damit einem keine anderen Interrupts durch die Lappen gehen.

Stell dir mal vor du bist in einer ISR die grad nen empfangenes Zeichen vom UART abholt und du verarbeitest alles in der ISR. Gleichzeitig hast du aber nen Timer laufen der dir alle paar Millisekunden eine andere ISR starten soll (zB wegen ner Multiplex-Anzeige). Dann verlierst du eventuell ein paar Timerinterrupts wenn du dir in der ISR für den UART zu viel Zeit läßt.

Es wird keiner der Timerinterrupts gespeichert. Du weist lediglich das in der Zwischenzeit ein TimerInterrupt ausgelöst wurde. Du weißt aber nicht ob es einer oder mehrere waren.

Gruß
Dino
 
Hallo und guten Morgen:)

Hallo,
Es wird keiner der Timerinterrupts gespeichert. Du weist lediglich das in der Zwischenzeit ein TimerInterrupt ausgelöst wurde. Du weißt aber nicht ob es einer oder mehrere waren.

...das heißt, man bekommt gar nicht mit, wenn während der Bearbeitung einer ISR ein anderer Interrupt ausgelöst wird?

Eine Andere Frage stellt sich mir noch zur Rangfolge von ISRs:
Ich glaube zwar die Antwort zu kennen, aber kann man dem Controler sagen, dass er einen bestimmten Interrupt IMMER bearbeiten soll? Das ist auch nicht ganz so Zeitkritisch. Dino hat den Nagel genau auf den Kopf getroffen:
Es handelt sich zum Einen um einen Timer, der im Sekundentakt eine Uhr im LCD und zwei Kleinigkeiten aktualisiert. Zum Anderen reagiert er auf das Zeichen [cr] an der "RS232"-Schnittstelle, zerlegt die Zeile vor diesem Zeichen und Antwortet ggf auf die Anfrage. Gerade dieses Antworten ist SEHR Zeitintensiv, da ich mit Waitms Pausen einfügen musste um eine vernünftige Datenübertragung zu bekommen. Lasse ich zum Beispiel das Waitms 100 weg, dann beginnt die Antwort immer mit den letzten 3 oder 4 Zeichen der zuvor empfangenen Frage (Hier wäre ich für eine Lösung/einen Lösungsansatz dankbar). Dieser Interrupt ist aber erheblich wichtiger als der Timer-Interrupt und sollte immer ausgeführt werden. Zeitlich unkritsich ist es, da der Master 300ms auf eine Antwort wartet, bis der nächste Slave befragt wird

Code:
Sub Serial0charmatch()
  'Daten vom Buffer auslesen
  Inputbin Dataincoming_byte
  If Dataincoming_byte = Datenpaket_startbyte_master Then
    Inputbin Dataincoming_byte
    Index = Geraeteadresse + Adressenoffset

    If Dataincoming_byte = Index Then                       ' Wenn meine Adress gesendet wurde...

      Inputbin Zeit
      Time$ = Zeit

      Rs485_senden = 1
      Led = 1
      Waitms 100
      ' Reihenfolge &-Geräteadresse-Lampe_aktive-CR
      Printbin Datenpaket_startbyte_slave ; Index ; Lampe_aktiv ; 13 ;
      Waitms 10
      Led = 0
      Rs485_senden = 0
    End If
  End If
  Clear Serialin
End Sub

Grüße
 
......kann man dem Controler sagen, dass er einen bestimmten Interrupt IMMER bearbeiten soll?


Hallo Oliver!

Nein, leider kann man dem AVR keine Prioritäten der Interrupts geben.
Die INT`s sind in ihrer Priorität festgeschrieben.

Damit du das Berücksichtigen kannst, gibt es die Vektortabelle im Datenblatt.
Hier mal ein Beispiel für einen Mega16:
INT-Vektortabelle_M16.gif


In der Tabelle kannst du sehen, dass der RESET immer die höchste Priorität besitzt. :wink:
Dann folgt schon der externe INT0, vor dem externen INT1.
Der TIMER0 kommt z.B. erst auf Platz 10 und so weiter.

Allerdings sind alle Timer-Interrupts VOR dem USART!
Das würde also bedeuten, dass dein "unwichtiger" Timer-Interrupt für den AVR wichtiger ist, als dein USART. :wink:


Grüße,
Cassio
 
...das heißt, man bekommt gar nicht mit, wenn während der Bearbeitung einer ISR ein anderer Interrupt ausgelöst wird?

Doch, das schon. Jeder Interrupt hat sein eigenes Interrupt-Anforderungsflag. Tritt der Interrupt auf, wird das ensprechende Flag gesetzt. Läuft gerade keine andere ISR, wird die ISR des aktuellen Interrupts ausgeführt. Läuft eine andere ISR, dann erst danach, wenn zwischenzeitlich mehrere unterschiedliche Interrupts aufgetreten sind, dann in der Reihenfolge wie sie Cassio beschrieben hat.

Was dir allerdings passieren kann, wenn eine gerade laufende ISR zu viel Zeit benötigt, dass dann ein mehrfaches auftreten eines Interrupts nicht erkannt wird.

Gruß,
Dirk
 
okay....

Doch, das schon. Jeder Interrupt hat sein eigenes Interrupt-Anforderungsflag. Tritt der Interrupt auf, wird das ensprechende Flag gesetzt. Läuft gerade keine andere ISR, wird die ISR des aktuellen Interrupts ausgeführt. Läuft eine andere ISR, dann erst danach, wenn zwischenzeitlich mehrere unterschiedliche Interrupts aufgetreten sind, dann in der Reihenfolge wie sie Cassio beschrieben hat.

...dann ist doch alles gut (naja,....)
Zwar ist es dann leider so, dass der unwichtige Timer bevorzugt wird, aber der USART-Interrupt wird ja nicht vergessen und "einfach etwas später" ausgeführt. Bei 8MHz sind 300ms ja doch schon eine halbe Ewigkeit, oder? Und ich hab mir den RS485-Bus so überlegt, dass selbst wenn ein Slave mal nicht Antwortet nichts passiert. Der Master macht dann einfach weiter und nutzt die Daten der letzten gültigen Übertragung. Bei der nächsten Runde fragt er dann erneut....

Bleibt noch das Problem mit den 100ms Wartezeit zwischen dem Umschalten des MAX485 in den Sendemodus und dem eigentlichen Senden der Daten. Ich glaube Cassio war es, der sagte ich solle nicht die Print/Input-Befehle nutzen sondern selber eine solche Routine schreiben, da man bei diesen Befehlen nicht sooo genau weiß was und wie sie machen, was sie machen. Ich scheu mich noch etwas davor...

Besten Dank für die Antworten
Oliver
 
Hi, noch zwei Ergänzungen:

- wenn man einen Interrupt (durch SEI) unterbrechbar macht, muß auf potentielle Stacküberläufe etc geachtet werden - insbesondere wenn der IRQ sich selbst unterbrechen kann (es werden ja bei jedem Interrupt-Eintritt die Rücksprungadresse und diverse Register (SREG + Rechenregister - bei Bascom und ohne nosave alle 32) auf den Stack gepusht. und beim Austritt wieder runtergepoppt. Wenn der Interrupt aber selbst durch einen Interrupt unterbrochen wird, wächst der Stack sehr schnell - die Stacklogik stimmt zwar noch, aber der verwendbare SRAM (den sich der Stack ja auch mit den anderen Datenbereichen teilen muß ("Framesize", "SWSTACK",...) ist endlich. Wenn der Stack dann also irgendwelche, eigentlich anders genutzten Bereiche überschreibt, oder Deine Daten die im Stack eigentlich gesicherten Register, kommt es zu schwer nachvollziehbaren Fehlern, klar.

- Auf die Priorität der Interrupts (Vektortabelle) und die generelle Abarbeitung wurde ja bereits grob eingegangen.
(Wenn der entsprechende Interrupt aktiviert ist, führt ein Eintreten des entsprechenden Ereignisses zum Setzen des entsprechenden Interruptanforderungsflags.
Wenn das Globale Interrupt-Flag (I) gesetzt ist, und mindestens ein Interruptanforderungsflag, wird (nach Abarbeitung des aktuellen Befehls) das Programm unterbrochen, Interrupts global unterbunden (I-Flag gelöscht), die Rücksprungadresse auf den Stack usw. Dann wird der Interruptvektor mit der höchsten Priorität (und aktivem InterruptAnforderungsFlag) ausgeführt. Dabei wird automatisch das entsprechende Interruptanforderungsflag zurrückgesetzt. Beim (regulärem) Austritt wird die Rücksprungadresse vom Stack genommen, und angesprungen, und das I-Flag wieder gesetzt - fertig. Da die anderen, ggf gesetzten Interruptanforderungsflags nicht verändert wurden, können diese jetzt abgearbeitet werden (wie oben bereits gesagt können dabei aber Interrupts verschluckt werden).

ABER:
es gibt auch levelbasierte Interrupts (ich finde allerdings nur bei den externen Interrupts was dazu) - da bewirkt dann nicht ein Anforderungsflag den Interrupt, sondern (zB) der Zustand des Pins. Und der kann übersehen werden, da er sich ja währen unterdrückter Interrupts (I-Flag) ändern kann...
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)