www.mikrocontroller.net

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


Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie ist denn b definiert?

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tommy (Gast)
Datum:

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

Autor: Peter (Gast)
Datum:

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

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab die Optimierung jetzt mal auf O0 gestellt, aber das Problem besteht 
weiterhin!

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann das sein das dir der Watchdog dazwischen funkt? Schalte ihn mal 
komplett ab.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tommy (Gast)
Datum:

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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steht auch im Assembler drin!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist Dir gar nicht aufgefallen, dass die Zeile
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.

Autor: Tommy (Gast)
Datum:

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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.