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
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
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.
>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?
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.
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