www.mikrocontroller.net

Forum: Compiler & IDEs Endlosschleife und Interrupt


Autor: M. I. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

machen die folgenden Codebeispiele für eine Endlosschleife einen 
Unterschied?
while(1);

while(1)
{
}

while(1)
{
   ;
}

Ich habe nämlich das Problem, dass eine Interrupt-Routine aufgerufen 
wird, wenn ein Interrupt während der Abarbeitung von "sinnvollem" Code 
eintrifft, aber wenn das Programm dann am Ende in die Endlosschleife 
läuft, reagiert die ISR nicht mehr.

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. I. wrote:
> machen die folgenden Codebeispiele für eine Endlosschleife einen
> Unterschied?

Nein.

> Ich habe nämlich das Problem, dass eine Interrupt-Routine aufgerufen
> wird, wenn ein Interrupt während der Abarbeitung von "sinnvollem" Code
> eintrifft, aber wenn das Programm dann am Ende in die Endlosschleife
> läuft, reagiert die ISR nicht mehr.

Das kann nicht sein, der Fehler hat sicherlich nichts mit der 
Endllosschleife zu tun. Zeig doch mal den kompletten Programmcode.

Autor: M. I. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Code kommt morgen. Es handelt sich aber nicht um einen AVR, und der 
Code besteht eigentlich nur aus Funktionen die den Interruptcontroller 
für diesen Prozessor (xilinx microblaze) vorbereiten.

Kann es auch sein, dass der Gnu-Debugger das nicht auf die Reihe 
bekommt? Kann es nämlich nur dort testen. Wenn er an die Stelle mit der 
Endlosschleife kommt erscheint die Windoof-Sanduhr und man kann nur noch 
durch Schließen des GDB das Programm abbrechen.

Autor: Power (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Außer dass bei
while(1);
das
do
{
}
(erzwungenes einmaliges durchlaufen der Bedingung) davor fehlt und
ich
while(1)
{
   ;
}
in der Form nicht kenne,
sollte das wirklich keinen Unterschied machen.

Autor: M. I. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bleibt also die Frage, ob ein Debugger mit sowas klar kommt, oder 
einfach abstürzt. Werd morgen mal einen Breakpoint auf die Schleife 
setzen.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Power:
Was hat das mit "do" zu tun? Genau, gar nichts. Die Schreibweise
while(1);
ist den anderen beiden völlig gleichwertig und sicher die kürzeste. Da 
fehlt gar nichts.

Autor: TechInfo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, hier der Quelltext. Die Funktionen werden euch nicht viel sagen, es 
sind Top-Level-Funktionen zur Initialisierung der Interrupts speziell 
für den xilinx microblaze.

Wenn ich während der Abarbeitung der Funktionen ein Zeichen in das 
Terminal eintippe, wird nach der letzten Init-Funktion 
(microblaze_enable_interrupts();) ein Interrupt ausgelöst (die ISR ist 
RecvCallback) und "Angekommen" auf dem Terminal ausgegeben. Wenn ich die 
Terminal-Eingabe allerdings erst in der while-Schleife vornehme, 
passiert nichts.

[c]
int main (void) {


  XInterruptHandler uart_int_handler;
  uart_int_handler=RecvCallback;


  /* Register UART interrupt handler */
  XIntc_RegisterHandler(XPAR_OPB_INTC_0_BASEADDR,
  XPAR_OPB_INTC_0_RS232_INTERRUPT_INTR, uart_int_handler, (void *)0);

  /* Start the interrupt controller */
  XIntc_mMasterEnable(XPAR_OPB_INTC_0_BASEADDR);

  /* Enable uart interrupts in the interrupt controller */
   XIntc_mEnableIntr(XPAR_OPB_INTC_0_BASEADDR,
         XPAR_RS232_INTERRUPT_MASK);
  /* Enable uart interrupts */
  XUartLite_mEnableIntr(XPAR_RS232_BASEADDR);
  /* Enable MicroBlaze interrupts */
  microblaze_enable_interrupts();

  while(1)
  {
  }
        return 0;
}

Autor: TechInfo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void RecvCallback (void* InstancePtr)
{
  print("Angekommen");
}

Autor: TechInfo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich irgendeinen Code in die while-Schleife packe, wie i++, 
funktioniert es übrigens auch in der Schleife.

Autor: Power (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  johnny.m:
Wann hast du das letzte mal in ein C-Buch geschaut? Kennst du den 
Unterschied zwischen
do
{
...
}
while (irgendwas=1);
und
while (irgendwas=1)
{
...
}
?
Nix für ungut, aber da ist ein gravierender Unterschied! Und man sollte 
sich nicht eine einfache Schreibweise angewöhnen die etwas anderes 
beinhaltet als nachher 'rauskommt, weil der Compiler wegen nie 
erfüllbarer Bedingung etwas Anderes draus optimiert.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Power wrote:
> @  johnny.m:
> Wann hast du das letzte mal in ein C-Buch geschaut? Kennst du den
> Unterschied zwischen
>
> do
> {
> ...
> }
> while (irgendwas=1);
> 
> und
>
> while (irgendwas=1)
> {
> ...
> }
> 
> ?
> Nix für ungut, aber da ist ein gravierender Unterschied!

Das ist schon richtig.

Aber das stand gar nicht zur Debatte.
Fakt ist, dass alle 3 Schreibweisen:
while(1);

while(1)
{
}

while(1)
{
   ;
}

absolut identisch sind und vor allen Dingen, völlig richtig.
Vor
 while(1);
fehlt keineswegs ein do.

Das ist eine ganz normale while-Schleife bei der der
Schliefenkörper aus einem einzigen Statement besteht,
nämlich aus dem leeren Statement.

Vielleicht siehst du das besser, wenn man das umformatiert

  while(1)
    ;

Vielleicht solltest du in ein C-Buch schauen :-)

> Und man sollte
> sich nicht eine einfache Schreibweise angewöhnen die etwas anderes
> beinhaltet als nachher 'rauskommt, weil der Compiler wegen nie
> erfüllbarer Bedingung etwas Anderes draus optimiert.

Im genannten Beispiel gibt es keine nie erfüllbaren
Bedingungen. Und auch mit Optimieren ist nichts. Eine
Endlosschleife kann auch der dümmste Compiler nicht
wegoptimieren.


Autor: Power (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>while(1)
>    ;

So isses richtig. Da bin ich drüber gestolpert. Habe mir eine saubere 
Strukturierung meiner Programme angewöhnt, so finde ich mich auch nach 
Jahren noch zurecht. Den Semikolon direkt hinter die Klammer zu setzen 
ist eben sehr verwirrend und sollte vermieden werden.
:-D

Autor: ??? ?? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was bedeutet die 1 in der Klammer? while(1)
Kann da auch was anderes stehen 2;3;;100?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
??? ?? wrote:
> Was bedeutet die 1 in der Klammer? while(1)
> Kann da auch was anderes stehen 2;3;;100?

C-Regel:
Alles was nicht 0 ist, hat den logischen Wert 'wahr' (true)

while( 1 )
  ;

ist also nichts anderes als

  while( TRUE )
    ;

oder

  while( 1 == 1 )

oder

  while( 5 )

oder
...

Der springende Punkt ist: Die Bedingung ist immer
wahr und daher kommt die Programmausführung aus dieser
Schleife durch Auswerten der Bedingung nicht mehr heraus
-> eine Endlosschleife ist entstanden.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Endlosschleife kann der Debugger vermutlich nicht als
Breakpoint benutzen.  Du versuchst offenbar, über diese Schleife
(mit einem Einzelschritt oder was auch immer) hinwegzugelangen,
was natürlich nicht geht.

Zum Debuggen ist es sicher am sinnvollsten, in die Schleife irgendeinen
minimalen Code einzufügen, z. B. einen Portausgabe oder sowas.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die frühen Microsoft Debugger hatten
bei solchen Dingen

   while(1);

auch so ihre Schwierigkeiten. Von da hab ich mir auch
angewöhnt, ein Statement (und wenn es nur ein leeres
Statement ist) in eine neue Zeile zu schreiben.

Mit

   while(1)
     ;

hatten diese Debugger niemals ein Problem.

Vielleicht hilfts ja jetzt auch noch.

Autor: ??? ?? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  Karl heinz
Vielen Dank für die Erklärung

Gruß

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Extra für Endlosschleifen gibt's bei for-Schleifen die Möglichkeit, die 
Bedingung auch einfach ganz wegzulassen:

for(;;)
    ;

  

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.