Forum: Compiler & IDEs UART-Interrupt


von Benjamin Munske (Gast)


Angehängte Dateien:

Lesenswert?

Hi Leute

Ich versuche gerade mit einem AT90s8515 serielle Übertragung
hinzubekommen. Und zwar mit dem Receive Complete Interrupt. Das Problem
ist, dass der Interrupt nicht einmal aufgerufen wird. So wie das
Programm jetzt aussieht blinken 3 LEDs an PORTD Pin 5-7. Der Interrupt
sollte als erstes diese LEDs ausschalten, aber nicht einmal das
passiert! Das Programm "hängt sich auf". Die LEDs bleiben an und
nichts geschieht mehr.

Ich hab schon im Forum gesucht, allerdings haben mir die gefundenen
Antworten nicht wirklich weiter geholfen.

Vielen Dank schonmal für eure Hilfe!

Benjamin

von Jörg Wunsch (Gast)


Lesenswert?

So ganz blicke ich mit der Mimik deiner LEDs nicht durch.  Du lässt
sie in main() blinken, in der ISR aber auch -- wie willst Du da
auseinanderhalten, wer wann was macht?  Die Abarbeitungszeit der ISR
ist so kurz, dass du das Ein- und Ausschalten (ich weiß gar nicht,
welche Polarität bei Dir was macht, in der Regel sind LED-Ausgänge
low-aktiv) innerhalb der ISR nie und nimmer beobachten kannst.

Außerdem, typischer Fehler: volatile beim Schreib- und Lesezeiger
vergessen (buf_read, buf_write).

Für eine sinnvolle Verzögerung benutze besser die Funktionen aus
<avr/delay.h>.

von Mirki (Gast)


Angehängte Dateien:

Lesenswert?

So ganz schlau werde ich aus deinen Beitrag auch nicht. Schaue dir mal
das Ding im Anhang an, dies waren so meine ersten schritte.

Häng doch mal in den eventhandler für das von Dir genannten Int eine
warteschleife ?! Vielleicht siehst Du ja dann auch die LED mal kurz
aufblinken.

Das Blinken solltest Du generell mal sein lassen, wenn du Dir die UDR
auslesung aneignen willst, ich glaub das verwirrt dich ein wenig.

Irgendjemand hier aus dem Forum sagte mal.

Lerne C lerne Debuggen ( oder so ähnlich )

von Benjamin Munske (Gast)


Lesenswert?

Hey vielen Dank für die schnelle Antwort.

Das Problem hab ich grad selber gelöst. Die Sache war die, dass ich
ITNERRUPT verwendet hatte. Es hätte aber SIGNAL heißen müssen. So wurde
der Interrupt scheinbar immer wieder aufgerufen, während die ISR noch
lief. Zumindest wenn ich den Unterschied zwischen INTERRUPT und SIGNAL
richtig verstanden haben.

Zu den LEDs: das ganze war so gedacht, dass ich durch das Blinken
erstmal die Bestätigung hatte, dass das Programm überhaupt läuft.
Danach habe ich versucht herauszufinden inwiefern die ISR überhaupt
arbeitet. (Mir war klar, dass sie irgendwo hängen bleibt... Die LEDs
haben nicht weiter geblinkt) Deshalb hab ich nach jedem Schritt in der
ISR eine LED angschaltet, um zu sehen wo es hängen bleibt.

Dumme Frage: (ich bin noch neu ich C) Was heißt volatile, bzw. was
bewirkt es?

Das mit dem delay wusst ich noch nicht. Danke.


Benjamin

PS: Bist du DER Jörg Wunsch? Der (Mit)Entwickler von AVR-libc? :-)

von Dirk (Gast)


Lesenswert?

Hi,

hier ist ein gutes Openbook da sollten einige Fragen beantwortet
werden.

http://www.pronix.de.speedpartner.de/modules/C/openbook/

von Jörg Wunsch (Gast)


Lesenswert?

Sorry, das mit dem INTERRUPT hätte ich natürlich sehen sollen.  Ja,
INTERRUPT statt SIGNAL in einer UART-ISR ist komplett tödlich.  Sofort
nach dem SEI im Prolog der ISR (das in diesem Falle bereits vom
Compiler erzeugt wird) löst die Hardware einen neuen Interrupt aus,
sodass diese verschachtelt werden ad nauseum.  Das hängt damit
zusammen, dass das hardwareseitige `interrupt pending' flag nicht
(wie
teilweise bei anderen Interrupts üblich) bereits beim Eintritt in die
ISR gelöscht wird sondern erst beim Lesen (bzw. Schreiben beim
Sender-Interrupt) von UDR.

> Was heißt volatile, bzw. was bewirkt es?

Die genaue Definition lässt sich im C-Stanard nachlesen.  Effektiv
bewirkt es, dass Zugriffe auf eine derart gekennzeichnete Variable
nicht mehr optimiert werden, sondern immer ausgeführt.  In deinem
Falle manipulierst du eine der Indexvariablen in einer ISR, aber die
Codeflussanalyse im Hauptprogramm merkt natürlich davon nichts.
Folglich könnte sie Zugriffe auf diese Variable u. U. komplett
optimieren (bspw. aus Schleifen herausziehen), da sich die Variable
nach Meinung des Optimizers ja ohnehin nicht ändern kann.

Das hat natürlich auch einen negativen Seiteneffekt.  Die Variable
wird dann wirklich jedesmal von ihrer Speicherstelle eingelesen,
auch innerhalb der ISR, wo sich ihr Wert ja wirklich nicht geändert
haben kann.  Besser als Deine Version wäre dann das Cachen in einer
temporären Variable innerhalb der ISR (das wird dann typisch ein
Register sein):

SIGNAL(SIG_UART_RECV)
{
  uint8_t buf_write_local = buf_write;

  // Hier ggf. auf Pufferüberlauf testen
  buffer[buf_write_local] = UDR;
  if (++buf_write_local >= MAXBUFFER) buf_write_local = 0;

  buf_write = buf_write_local;
}

> Bist du DER Jörg Wunsch?

Ganz bestimmt.  Wer denn sonst? :-)  DIE Jörg Wunsch jedenfalls
nicht. ;-)

> Der (Mit)Entwickler von AVR-libc?

*Mit*Entwickler, ja, wohl mittlerweile.  Der Entwickler der avr-libc
war/ist Marek Michalkiewicz, auch wenn er mittlerweile nicht mehr ganz
so aktiv ist.

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.