Problem mit itoa() Funktion

Gast #1228130
Lesenswert?

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
Gast #1228157
Lesenswert?

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!
Gast #1228182
Lesenswert?

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
#1228193
Lesenswert?

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.
Gast #1228205
Lesenswert?

>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
#1228227
Lesenswert?

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.
Gast #1228228
Lesenswert?

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
#1228256
Lesenswert?

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)
Gast #1228264
Lesenswert?

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
#1228271
Lesenswert?

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.
Gast #1228299
Lesenswert?

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
#1228306
Lesenswert?

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.
Gast #1228335
Lesenswert?

>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
Gast #1228970
Lesenswert?

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
Gast #1231325
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren