Habe folgendes Problem: Wenn ich die itoa Funktion benutze springt mein Programm an die folgende Adresse: siehe Code, letzte Zeile itoa(time,b,10); +00000093: 91800102 LDS R24,0x0102 Load direct from data space +00000095: E04A LDI R20,0x0A Load immediate +00000096: E050 LDI R21,0x00 Load immediate +00000097: 01BE MOVW R22,R28 Copy register pair +00000098: 5F6F SUBI R22,0xFF Subtract immediate +00000099: 4F7F SBCI R23,0xFF Subtract immediate with carry +0000009A: 2799 CLR R25 Clear Register +0000009B: 940E0207 CALL 0x00000207 Call subroutine //HIER Das Verstehe ich nicht! Mein JTAG ICE MK2 springt immer an diese Adresse, aber das ist doch eine Standartfunktion, also gar nicht von mir Programmiert. Kann mir jemand erklären warum das so ist? Normalerweise müsste er doch wieder an die letzte Stack Adresse springen, habe die stdlib inkludiert! Gruß Tommy p.s Ich programmiere in C mit dem AVR Studio und verwende einen ATmega 162
Hallo, ich verstehe Deine Frage nicht. Er sammelt die Parameter zusammen und ruft eine Subroutine bei +0000009B: 940E0207 CALL 0x00000207 Call subroutine auf, vermutlich die itoa-Routine. Was ist Dir da unklar? gruß aus berlin Michael
Hallo Michael Hier ist mein Prgramm: Es zählt einfach bis 5 und fängt dann wieder von vorne an include<avr/io.h> #include<stdlib.h> #include<avr/interrupt.h> #include<avr/wdt.h> #include"timer.h" #include"uart.h" volatile uint8_t time=0; ISR(TIMER2_OVF_vect) { time++; if(time>17) wdt_enable(1); } int main() { DDRC=0xff; timer2_init(); sei(); while(1) { PORTC=time; if(time==5) { itoa(time,b,10); time=0; } } return 0; } Wenn der debugger in die itoa Zeile reinkommt springt er aufeinmal in diese Zeile: #include <avr/io.h> void timer2_init() { ASSR=0x08; TCCR2=0x05; TIMSK=0x04; //hier springt er hin } Das Versteh ich nicht!
Tommy wrote: > Hallo Michael > Hier ist mein Prgramm: Ne, das ist nur ein leider unbrauchbarer Fetzen davon. > { itoa(time,b,10); Was soll das itoa denn da?
Das Programm hat keinen tieferen Sinn. Ich will nur verstehen warum der Debugger dorthin springt! Das dürfte doch eigentlich nicht sein. Das Bedeutet doch, dass in den paar Zeilen schon ein Fehler sein muss, aber wo? Das ist der Grund weshalb ich Frage! Ich will es einfach nur verstehen Gruß Tommy
Oh, b hatte ich ganz vergessen hinzuschreiben, ist aber im Programm wie folgt definiert: char b[10];
wenn wir nicht wissen die b definiert ist, werden wir auch den Fehler nicht finden. Mann sollte schon alles mitschicken von dazugehört!
Hallo, gut, die Fragen wurden schon gestellt, wie sind die Variablen definert, speziell b, was soll itoa da machen und welche Optimierung Du benutzt hast wäre noch von Bedeutung. Gruß aus Berlin Michael
Eigentlich wollte ich über die UART dann b ausgeben, aber da der Debugger so komisch gesprungen ist, habe ich die UART weggelassen um eine Fehlerquelle ausschließen zu können. Optimert ist es mit Os. Ich habe b nicht mit einem Wert initialisiert! Deklariert ist b über der DDRC=0xff Zeile, unter "int main()" Muss ich b vielleicht am Anfang einen Wert zuweisen? Liegt da der Fehler? Gruß Tommy
Hab die Optimierung jetzt mal auf O0 gestellt, aber das Problem besteht weiterhin!
kann das sein das dir der Watchdog dazwischen funkt? Schalte ihn mal komplett ab.
Tommy wrote: > Das Verstehe ich nicht! Mein JTAG ICE MK2 springt immer an diese > Adresse, aber das ist doch eine Standartfunktion, also gar nicht von mir > Programmiert. Aber auch eine "Standardfunktion" besteht aus Code, der ausgeführt werden muss, und der daher beim Aufruf dieser Funktion "angesprungen" wird. Dieser Code kommt aus einer Bibliothek und wird deinem Programm beim Linken hinzugefügt.
Ja, das versteh ich schon, aber dann sollte er doch auch in die entsprechende Routine springen und nicht in die Initialisierung des Timers Gruß Tommy
>Liegt da der Fehler? Welcher Fehler? Macht das Programm das, was du willst, oder nicht? >Optimert ist es mit Os. Bei jeder Optimierung (ausser -O1) geht der Zusammenhang zwischen den C-Code-Zeilen und dem, was der Compiler draus macht, ziemlich verloren. Profis können den Assembler-Code direkt lesen, für alle anderen ist es am einfachsten, zum Debuggen ohne Optimierung zu kompileren. Oliver
Tommy wrote: > Ja, das versteh ich schon, aber dann sollte er doch auch in die > entsprechende Routine springen und nicht in die Initialisierung des > Timers Springt er denn wirklich dahin (im Assembler-Code) oder zeigt dir nur der Debugger im C-Code an, dass er dorthin springt? Der Debugger hat nämlich schon mal Probleme die C-Code-Zeilen entsprechend zuzuordnen.
Habe jetzt mal die UART mit eingebunden und ich bekomme über die UART auch eine 5 gesendet, aber trotzdem springt der Debugger in der itoa Zeile zuerst in folgende Zeile: #include <avr/io.h> void timer2_init() { ASSR=0x08; TCCR2=0x05; TIMSK=0x04; //hier springt er hin } Es geht mir nicht so sehr darum, dass das Programm läuft, ich würde gern wissen warum der Debugger mir das anzeigt! Habe es mal mit der Optimierung O1 versucht, aber gab auch kein Erfolg! Es ist doch nicht richtig das er dort hinspringt, dafür muss es doch eine Erklärung geben! gruß Tommy
Die normalen Erklärung bei solch seltsamen Verhalten sind meistens * irgendwo in der IDE ist ein Konfigurationsfehler Entweder hat der Compiler Code für den falschen Prozessor generiert oder der Simulator ist auf den falschen Prozessor eingestellt oder der Debugger .... * Der Optimizer ist noch immer eingeschaltet * Im µC läuft ein ganz anderes Programm als der Debugger denkt (sprich: Wahlweise beim Compilieren/Linken/Flashen ist irgendwas schief gegangen, sodass der angezeigte Source Code nichts mit im µC laufenden Programm zu tun hat, bzw. Zeilennummern nicht mehr übereinstimmen. * Der Debugger hat einen Fehler * Der Compiler hat einen Fehler (wobei die letzten beiden Punkte zwar die sind, an die alle als erstes denken. Nur sind sie es in den seltensten Fällen)
Tommy wrote:
> Steht auch im Assembler drin!
Der Sprung an sich natürlich schon, aber wo geht er hin?
Poste doch einfach mal das ganze Assembler-Listing.
Ich glaube die ganz Liste wäre ein bisschen viel! Hier ist der interessante Teil: 34: { itoa(time,b,10); +00000083: 91800100 LDS R24,0x0100 Load direct from data space +00000085: E04A LDI R20,0x0A Load immediate +00000086: E050 LDI R21,0x00 Load immediate +00000087: 01B8 MOVW R22,R16 Copy register pair +00000088: 2799 CLR R25 Clear Register +00000089: 940E020B CALL 0x0000020B Call subroutine und in die Zeile x0000020B springt er hin! +00000204: E088 LDI R24,0x08 Load immediate +00000205: BD86 OUT 0x26,R24 Out to I/O location 6: TCCR2=0x05; //quarzfrequenz wird durch 128 geteilt! 32768/128=256 +00000206: E085 LDI R24,0x05 Load immediate +00000207: BD87 OUT 0x27,R24 Out to I/O location 12: TIMSK=0x04; //timeroverflow interrupt aktiviert +00000208: E084 LDI R24,0x04 Load immediate +00000209: BF89 OUT 0x39,R24 Out to I/O location +0000020A: 9508 RET Subroutine return 12: TIMSK=0x04; //timeroverflow interrupt aktiviert +0000020B: 01FB MOVW R30,R22 Copy register pair +0000020C: 019F MOVW R18,R30 Copy register pair +0000020D: 94E8 CLT Clear T in SREG +0000020E: 3042 CPI R20,0x02 Compare with immediate +0000020F: F0C4 BRLT PC+0x19 Branch if less than, signed +00000210: 3245 CPI R20,0x25 Compare with immediate +00000211: F4B4 BRGE PC+0x17 Branch if greater or equal, signed +00000212: 304A CPI R20,0x0A Co
Oh, ich sehe gerade: Kann es sein, das er eine Zeile tiefer springt als er Anzeigt? Das würde dann bedeuten, dass der Degugger NICHT das macht was das Programm macht, richtig? gruß Tommy Wenn es so wäre, wie soll man dann sich auf das JTAG verlassen können?
Ist Dir gar nicht aufgefallen, dass die Zeile
1 | TIMSK=0x04; //timeroverflow interrupt aktiviert |
zweimal auftaucht und das, was hinter dem zweiten Mal (und hinter dem ret aus der Timer-Init!) steht, gar nichts mit dem TIMSK zu tun hat? Die zweite Zeile mit obigem Inhalt ist an der Stelle einfach fehl am Platze. Warum die da steht, kann man so nicht sagen.
Augen sollte man auch benutzen. Du hast recht. Vielleicht liegts ja an der Timer Initialisierung! Gruß Tommy
Wenn ich die itoa Funktion rausnehme finde ich folgendes im Assembler: +000001F9: BD86 OUT 0x26,R24 Out to I/O location 6: TCCR2=0x05; //quarzfrequenz wird durch 128 geteilt! 32768/128=256 +000001FA: E085 LDI R24,0x05 Load immediate +000001FB: BD87 OUT 0x27,R24 Out to I/O location 12: TIMSK=0x04; //timeroverflow interrupt aktiviert +000001FC: E084 LDI R24,0x04 Load immediate +000001FD: BF89 OUT 0x39,R24 Out to I/O location +000001FE: 9508 RET Subroutine return 12: TIMSK=0x04; //timeroverflow interrupt aktiviert +000001FF: CFFF RJMP PC-0x0000 Relative jump +00000200: 0068 ??? Data or unknown opcode +00000201: FFFF ??? Data or unknown opcode +00000202: FFFF ??? Data or unknown opcode +00000203: FFFF ??? Data or unknown opcode +00000204: FFFF ??? Data or unknown opcode +00000205: FFFF ??? Data or unknown opcode +00000206: FFFF ??? Data or unknown opcode +00000207: FFFF ??? Data or unknown opcode +00000208: FFFF ??? Data or unknown opcode +00000209: FFFF ??? Data or unknown opcode +0000020A: FFFF ??? Data or unknown opcode +0000020B: FFFF ??? Data or unknown opcode +0000020C: FFFF ??? Data or unknown opcode +0000020D: FFFF ??? Data or unknown opcode +0000020E: FFFF ??? Data or unknown opcode +0000020F: FFFF ??? Data or unknown opcode Da taucht TIMSK=0x04 auch zweimal auf! Kann das vielleicht an den Inkludes liegen? Ich weiß nicht was an der Timerinitialisierung falsch sein soll! Ich glaube daran liegt es nicht Gruß Tommy
Tommy wrote: > +000001FE: 9508 RET Subroutine return > 12: TIMSK=0x04; //timeroverflow interrupt aktiviert > +000001FF: CFFF RJMP PC-0x0000 Relative jump > +00000200: 0068 ??? Data or unknown opcode > +00000201: FFFF ??? Data or unknown opcode > Da taucht TIMSK=0x04 auch zweimal auf! Kann das vielleicht an den > Inkludes liegen? Ich weiß nicht was an der Timerinitialisierung falsch > sein soll! Wer sagt denn, dass da was falsch ist? Die Codezeile hat keinen Einfluss auf das Programm. Warum die da steht, ist, wie schon gesagt, im Prinzip egal. Der Sprung dahin wird wohl richtig sein. In der obigen Version ohne itoa steht da ein "RJMP PC-0x0000" vor dem "ungültigen Code", der den Rest des Speichers füllt, und genau so soll es auch sein. Was in der Version mit itoa da steht, wird wohl zu besagter Funktion gehören.
Tommy wrote:
> Ich weiß nicht was an der Timerinitialisierung falsch sein soll!
Es ist nichts falsch am Code.
Der Debugger hat nur Probleme den Assembler-Code dem C-Code passend
zuzuordnen. Das ist nur ein "Anzeigeproblem", kein wirklich vorhandenes
Problem.
Es scheint wirklich so zu sein, da ich ja auch das richtige Ergebnis angezeigt bekomme (wenn ich die UART aktiviere!). Es ist nur nicht sehr befriedigend, wenn der Debugger so etwas macht! Schließlich soll er vermeiden Fehler zu machen und nicht welche Produzieren. Gruß Tommy
>Ich glaube daran liegt es nicht Es liegt überhaupt nicht an deinem Programm. Vielleicht habe ich mich weiter oben unklar ausgedrückt. Also nochmals deutlich: Wenn du mit -Os (oder -O2 oder -O3) kompilierst, würfelt der Compilers den Code so durcheinander, daß er kaum mehr was mit den Original-C-Code-Zeilen zu tun hat. Alles, was der Debugger im C-Code dann anzeigt, kann sinnvoll sein, kann aber völliger Blödsinn sein. >Kann es sein, das er eine Zeile tiefer springt als >er Anzeigt? Das würde dann bedeuten, dass der Degugger NICHT das macht >was das Programm macht, richtig? Richtig. Und falsch. Der Debugger macht schon genau das, was das Programm macht - das Assemblerprogramm. Da das kompilierte Asssmeblerprogramm aber nicht mehr 1:1 dem C-Code entspricht, zeigt der Debugger manchmal Blödsinn an. Mit Optimierung macht das Prgramm zwar das, WAS du willst, aber nicht so, WIE du willst. >Wenn es so wäre, wie soll man dann sich auf das JTAG verlassen können? Entweder im Assemblercode debuggen, oder eben ohne Optimierung. Oder sich durch die "komischen" Debuggeranzeigen nicht verwirren lassen. Manches passt ja immer noch. Oliver
Hallo Oliver, folgendes interessantes ist jetzt passiert! Ich habe in den Options, die Kompremierung auf O1 gestellt. Also: Keine Komprimierung Der Assembler Code zeigt mir auch alles richtig an, wenn ich Zeile für Zeile durch das Programm gehe, aber wenn ich in C bleibe Springt er an diese Stelle: #include <avr/io.h> void timer2_init() { ASSR=0x08; TCCR2=0x05; TIMSK=0x04; //hier springt er hin } Also eine Zeile höher als er sollte. Trotz ohne Komprimierung! Wie kann das sein? Und noch etwas interessantes ist aufgetreten: Ich habe ein weitaus größeres Programm welches sich immer aufgehangen hat. Seitdem ich die itoa Funktion rausgenommen habe läuft es Fehlerfrei! Ist doch auch komisch oder Gruß Tommy
> die Kompremierung auf O1 gestellt.
Omtimierungstufe O1 optimiert immer noch, wenn auch nicht so heftig wie
die größeren Stufen. Ohne Optimierung wäre -O0.
Oliver
Hallo Oliver, ich muss mich auch berichtigen! Ich hatte ja gesagt, dass seit der Entfernung der ito Funktion die Software fehlerfrei läuft! Das stimmte so nicht. Zwar läuft die Software jetzt, aber es lag daran, dass mein Netzteil mein Prototypen gestört hat. Gemerkt habe ich es erst, als ich den Prototypen über Batterie mit Spannung versorgt habe und beim Einschalten des Netzteils, hat der Prototyp drauf reagiert, obwohl das Netzteil gar nicht angeschlossen ist! Gruß Tommy
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.