Hallo,
machen die folgenden Codebeispiele für eine Endlosschleife einen
Unterschied?
1
while(1);
2
3
while(1)
4
{
5
}
6
7
while(1)
8
{
9
;
10
}
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.
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.
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.
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;
}
@ johnny.m:
Wann hast du das letzte mal in ein C-Buch geschaut? Kennst du den
Unterschied zwischen
1
do
2
{
3
...
4
}
5
while(irgendwas=1);
und
1
while(irgendwas=1)
2
{
3
...
4
}
?
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.
Power wrote:
> @ johnny.m:> Wann hast du das letzte mal in ein C-Buch geschaut? Kennst du den> Unterschied zwischen>
1
>do
2
>{
3
>...
4
>}
5
>while(irgendwas=1);
6
>
> und>
1
>while(irgendwas=1)
2
>{
3
>...
4
>}
5
>
> ?> 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:
1
while(1);
2
3
while(1)
4
{
5
}
6
7
while(1)
8
{
9
;
10
}
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.
>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
??? ?? 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.
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.
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.