Forum: Compiler & IDEs SIGNAL geht INTERRUPT nicht ???


von Christian (Gast)


Lesenswert?

Hallo allerseits,
folgendes Problem:
Daten die über die serielle Schnittstelle den MC erreichen sollen ans
Display geschrieben werden. Das geht mit folgendem CODE Schnipsel
prima:

SIGNAL(SIG_UART_RECV)
{
  putchar_lcd(inp(UDR));
}

Warum aber hauts nicht hin wenn man anstelle von SIGNAL INTERRUPT
schreibt?? Die Zeichen kommen so langsam an den MC dass die
Displayroutine mit Sicherheit abgearbeitet ist bevor das nächste byte
kommt....

Freu mich auf eure Antworten!!
Vielen Dank

Christian

von Joerg Wunsch (Gast)


Lesenswert?

> Warum aber hauts nicht hin wenn man anstelle von SIGNAL INTERRUPT
> schreibt?

Weil Du den Unterschied zwischen beiden entweder nicht verstanden hast
und/oder das Datenblatt nicht richtig gelesen.  Besonders
SIG_UART_RECV ist absolut ungeeignet für INTERRUPT(), das das
schlagartig zu einer endlosen Rekursion führt.

von Eugen Dischke (Gast)


Lesenswert?

ma ne frage ich hab bisher angenommen, das es kein unterschied gibt zw
interrupt und signal kann mich ma einer aufklären
MfG eugen

von Florian Pfanner (Gast)


Lesenswert?

Hab gerade mal die AVR-Libc durchgeschaut. Hab aber keine eindeutige
zuweisung gefunden.
Aber grundsätzlich: Wenn ich mich nicht täusche, so ist Signal() ein
ganz normaler Interrupt. Wenn du jedoch Interrupt() schreibst, so ist
der erste ASM-Befehl in der Routiene sei. Also gleich nach dem Betreten
der Interruptschleife werden die Interrupts wieder freigegeben. Wenn
aber das Interrupt-Flag von der Hardware noch nicht gelöscht wurde, so
wird der Interrupt sofort wieder aufgerufen. Das geht so lange bis dein
Stack überläuft.
Ich weiß nicht wozu man die Interrupt() braucht, ich habs bis jetzt
immer von Hand gemacht: Interruptroutiene mit Signal(), dann das
dazugehörige Interrupt-Flag gelöscht und erst dann wieder eine Globale
Interruptfreigabe.

Gruß, Florian

von Joerg Wunsch (Gast)


Lesenswert?

> Aber grundsätzlich: Wenn ich mich nicht täusche, so ist Signal() ein
> ganz normaler Interrupt. Wenn du jedoch Interrupt() schreibst, so
> ist der erste ASM-Befehl in der Routiene sei.

Genau so ist es (außer daß sich beide komplett GROSS schreiben -- C
unterscheidet zwischen Groß-/Kleinschreibung).

Ich verstehe auch gar nicht, warum das aus der Doku so schwierig
herauszulesen sein soll:

SIGNAL():

Introduces an interrupt handler function that runs with global
interrupts initially disabled.

INTERRUPT():

Introduces an interrupt handler function that runs with global
interrupts initially enabled. This allows interrupt handlers to be
interrupted.

> Ich weiß nicht wozu man die Interrupt() braucht, ...

Die Grundregel #1 ist: wenn Du nicht weißt, wofür Du es brauchst, dann
brauchst Du es nicht. ;-)

In der Tat braucht man das wohl eher für Spezialfälle, bei denen man
keine Zeit damit vergeuden will, die Interrupts sofort wieder
freizugeben, um andere (zeitkritische) Interrupts nicht zu verzögern.
Logischerweise kann man es nur bei Interrupts benutzen, die sich nicht
aufgrund des Hardware-Flags sofort wieder selbst auslösen würden.

Meiner Meinung nach sind sie etwas unglückselig benannt, so daß zu
viele Leute geneigt sind, INTERRUPT() überhaupt in Betracht zu ziehen.

von Christian (Gast)


Lesenswert?

Hallo zusammen und vielen Dank für eure Antworten!!!

ich konnte das Problem jetzt recht erfolgreich ohne "Interrupt"
(sondern mit Signal) lösen, allerdings ist mir immer noch nicht klar
warums nicht funktioniert hat, auch wenn ich innerhalb der Interrupt
routine lediglich den Empfangswert der seriellen schnittstelle in eine
andere Variable kopiert habe??

Macht aber nix - brauchs ja jetzt nicht mehr .....

Danke für eure Hilfe und alles Gute fürs neue Jahr!!

Christian

von Joerg Wunsch (Gast)


Lesenswert?

> ich konnte das Problem jetzt recht erfolgreich ohne "Interrupt"
> (sondern mit Signal) lösen, allerdings ist mir immer noch nicht klar
> warums nicht funktioniert hat, auch wenn ich innerhalb der Interrupt
> routine lediglich den Empfangswert der seriellen schnittstelle in
> eine andere Variable kopiert habe?

Weil Du nur mit trial & error arbeitest und leider immer noch nicht
verstanden hast, was Du denn überhaupt tust.

,,lediglich den Empfangswert ... kopiert'' ist halt exakt die
Operation (lesen von UDR), die die anhängige Interruptbedingung wieder
zurücknimmt.  Wenn Du zuvor aber bereits die globalen Interrupts
wieder freigibst (wie es in INTERRUPT() ja passiert), dann wird sofort
nach dem SEI ein neuer Interrupt ausgelöst (für das gleiche Ereignis),
was unweigerlich zum Stacküberlauf führt.

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.