Forum: Mikrocontroller und Digitale Elektronik Problem mit itoa() Funktion


von Tommy (Gast)


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

von Michael U. (amiga)


Lesenswert?

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

von Tommy (Gast)


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!

von Sven P. (Gast)


Lesenswert?

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?

von Peter (Gast)


Lesenswert?

wie ist denn b definiert?

von Tommy (Gast)


Lesenswert?

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

von Tommy (Gast)


Lesenswert?

Oh, b hatte ich ganz vergessen hinzuschreiben, ist aber im Programm wie 
folgt definiert:
char b[10];

von Peter (Gast)


Lesenswert?

wenn wir nicht wissen die b definiert ist, werden wir auch den Fehler 
nicht finden. Mann sollte schon alles mitschicken von dazugehört!

von Michael U. (amiga)


Lesenswert?

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

von Tommy (Gast)


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

von Tommy (Gast)


Lesenswert?

Hab die Optimierung jetzt mal auf O0 gestellt, aber das Problem besteht 
weiterhin!

von Peter (Gast)


Lesenswert?

kann das sein das dir der Watchdog dazwischen funkt? Schalte ihn mal 
komplett ab.

von Stefan E. (sternst)


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.

von Tommy (Gast)


Lesenswert?

Hab ich gemacht, aber daran liegts auch nicht!
Gruß Tommy

von Tommy (Gast)


Lesenswert?

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

von Oliver (Gast)


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

von Stefan E. (sternst)


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.

von Tommy (Gast)


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

von Tommy (Gast)


Lesenswert?

Steht auch im Assembler drin!

von Karl H. (kbuchegg)


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)

von Stefan E. (sternst)


Lesenswert?

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.

von Tommy (Gast)


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

von Tommy (Gast)


Lesenswert?

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?

von Johannes M. (johnny-m)


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.

von Tommy (Gast)


Lesenswert?

Augen sollte man auch benutzen. Du hast recht. Vielleicht liegts ja an 
der Timer Initialisierung!
Gruß Tommy

von Tommy (Gast)


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

von Johannes M. (johnny-m)


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.

von Stefan E. (sternst)


Lesenswert?

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.

von Tommy (Gast)


Lesenswert?

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

von Oliver (Gast)


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

von Tommy (Gast)


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

von Oliver (Gast)


Lesenswert?

> 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

von Tommy (Gast)


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

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
Noch kein Account? Hier anmelden.