Forum: Compiler & IDEs Problem mit string.


von martin (Gast)


Lesenswert?

Hallo,

folgender Code:

char text[] ="HelloAVR";
text[0]='H';
text[1]='e';
for(int ci=0; text[ci] != '\0'; ++ci)
{
   putch(text[ci]);
}
putch('\n');

(putch gibt das Zeichen auf dem uart aus, geht auch)

erzeugt folgende Ausgabe auf dem Terminal:
Heì\0x01\0x0f\0x01\0x03\0x02

Das verstehe ich nicht. warum funktioniert die Zuweisung in der 
initialisierung nicht?

Vielleicht kann mir jemand einen Tip geben?

Danke!
MFG
Martin

von Stefan (Gast)


Lesenswert?

Das ist kein komplettes Programm. Die Ursache kann in dem nicht 
angegebenen Teil stecken.

von martin (Gast)


Lesenswert?

#include <avr/io.h> // I/O Funktionen
#include <stdint.h> // Datentypen z.B. uint32_t
#include <avr/pgmspace.h>
#define F_CPU      14745600UL
#include <util/delay.h>
#include <string.h>


#define HW_VER   0x02
#define SW_MAJOR 0x01
#define SW_MINOR 0x12
#define BAUD_RATE    115200
#define DECRYPT 0
#define ENCRYPT 1
#define SIG1  0x1E
#define SIG2  0x97
#define SIG3  0x02
#define PAGE_SIZE  0x80U  //128 words
#define UART1


#define LED_DDR  DDRB
#define LED_PORT PORTB
#define LED_PIN  PINB
#define LED      PINB7

#define SW_DDR  DDRF
#define SW_PORT PORTF
#define SW_PIN  PINF
#define SW0     PINF7 //Schalter0 an Pin 7
#define SW1     PINF6 //Schalter1 an Pin 6
#define mswait 10

struct flags_struct {
  unsigned flag_1 : 1; // Schalter; 0: SW0 1: SW1
  unsigned flag_2 : 1;
  unsigned flag_3 : 1;
  unsigned flag_4 : 1;
  unsigned flag_5 : 1;
  unsigned flag_6 : 1;
  unsigned flag_7 : 1;
  unsigned flag_8 : 1;
} flags;

void wait10ms(uint16_t xms);
void inituart(void);
void lese_Schalter(void);
void putch(char ch);
char getch(void);

int main(void)
{
  flags.flag_2 = 0;
  SW_DDR &= ~(1 << SW0); //Ausgang=1 Eingang=0 daher l?schen
  SW_DDR &= ~(1 << SW1);
  SW_PORT |= (1 << SW0); //Bei Eingang steuer Port die 
Pull-up-Widerst?nde!
  SW_PORT |= (1 << SW1); // hier: Pull-up auf EIN!

  asm volatile("nop\n\t");
  LED_DDR |= (1 << LED); // LED auf Ausgang
  LED_PORT &= ~(1 << LED); // LED EIN
  inituart();

  for (;;)
  {
           char text[] = "HelloAVR";
           //PGM_P text = {"HelloAVR"};
           text[0]='H';
     text[7]='R';
  for(int ci=0; text[ci] != '\0'; ++ci)
  {
    putch(text[ci]);
  }
  putch('\n');
}
  }
}

void inituart()
{
    UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
    UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
    UCSR1A = 0x00; //
    UCSR1C = 0x06;
    UCSR1B = _BV(TXEN1)|_BV(RXEN1);

    // bei neueren AVRs steht der Status in UCSRA/UCSR0A/UCSR1A
    while (!(UCSR1A & (1<<UDRE)))  // warten bis Senden moeglich
    {
    }

    PGM_P welcome = {"HelloAVR; Matthias Vogt - build 070106\n\r"};
  for(int i=0; welcome[i] != '\0'; ++i)
  {
    putch(welcome[i]);
  }
}

void putch(char ch)
{
   while (!(UCSR1A & _BV(UDRE1)));
   UDR1 = ch;
}

char getch(void)
{
  while(!(UCSR1A & _BV(RXC1)));
    return (UDR1);
}

von martin (Gast)


Lesenswert?

Neuere Versin, sorry. Diese geht aber genausoenig!



#include <avr/io.h> // I/O Funktionen
#include <stdint.h> // Datentypen z.B. uint32_t
#include <avr/pgmspace.h>
#define F_CPU      14745600UL
#include <util/delay.h>
#include <string.h>


#define HW_VER   0x02
#define SW_MAJOR 0x01
#define SW_MINOR 0x12
#define BAUD_RATE    115200
#define DECRYPT 0
#define ENCRYPT 1
#define SIG1  0x1E
#define SIG2  0x97
#define SIG3  0x02
#define PAGE_SIZE  0x80U  //128 words
#define UART1


#define LED_DDR  DDRB
#define LED_PORT PORTB
#define LED_PIN  PINB
#define LED      PINB7

#define SW_DDR  DDRF
#define SW_PORT PORTF
#define SW_PIN  PINF
#define SW0     PINF7 //Schalter0 an Pin 7
#define SW1     PINF6 //Schalter1 an Pin 6
#define mswait 10

void wait10ms(uint16_t xms);
void inituart(void);
void lese_Schalter(void);
void putch(char ch);
char getch(void);

int main(void)
{
  SW_DDR &= ~(1 << SW0); //Ausgang=1 Eingang=0 daher l?schen
  SW_DDR &= ~(1 << SW1);
  SW_PORT |= (1 << SW0); //Bei Eingang steuer Port die
Pull-up-Widerst?nde!
  SW_PORT |= (1 << SW1); // hier: Pull-up auf EIN!

  asm volatile("nop\n\t");
  LED_DDR |= (1 << LED); // LED auf Ausgang
  LED_PORT &= ~(1 << LED); // LED EIN
  inituart();

  for (;;)
  {
     char text[] = "HelloAVR";
     text[0]='H';
     text[7]='R';
     for(int ci=0; text[ci] != '\0'; ++ci)
     {
        putch(text[ci]);
     }
     putch('\n');
   }
}

void inituart()
{
    UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
    UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
    UCSR1A = 0x00; //
    UCSR1C = 0x06;
    UCSR1B = _BV(TXEN1)|_BV(RXEN1);
}

void putch(char ch)
{
   while (!(UCSR1A & _BV(UDRE1)));
   UDR1 = ch;
}

char getch(void)
{
  while(!(UCSR1A & _BV(RXC1)));
    return (UDR1);
}

von martin (Gast)


Lesenswert?

Den Code des Programmes hab ich übrigens hauptsächlihc aus Beispielen 
aus dem Internet zusammenkopiert, auch den Teil mit dem String,daher 
könnte der Fehler auch irgendwo anders liegen.

Gruß
Martin

von martin (Gast)


Lesenswert?

mit der EZuweisung scheint aber was fault zu sein.
     char text[] = "HelloAVR";
hier:
     text[0]='H';
     text[7]='R';
habe ich das ja eingefügt, und "H" und "R" kommen an. nur der Rest der 
nicht nochmal neu zugewiesen wird wird "zerstückelt":
"aH%ì\0x01\0x0f\0x01\0x03R"

als Hexdump:
0x61 a
0x48 H
0x25 EM
0xec
0x01 SOH
0x0f SI
0x01 SOH
0x03 ETX
0x52 R
0x0a LF
 a,H,R,LF sind OK.

von Stefan (Gast)


Lesenswert?

Ich rate anhand der Namen der IO-Register, dass es für einen Atmega128 
sein soll.

Sourcecode #2 kompiliert nicht mit:

AVR Studio    4.12.498  Service Pack 4
GUI Version    4, 12, 0, 491
AVR Simulator    1, 0, 1, 8
ATMEGA8    243

Operating System
Major      4
Minor      10
PlatformID    1
Build      67766446
 A

Plugins:
AVRPLUGINAVRASMOBJECT  1, 0, 0, 43
STK500DLL      1, 0, 1, 0
AVRPLUGINAVRGCCPLUGIN  1, 0, 0, 6

Fehlermeldungen im Build-Fenster:

Build started 7.1.2007 at 16:49:44
avr-gcc.exe  -mmcu=atmega128 -Wall -gdwarf-2  -O0 -fsigned-char -MD -MP 
-MT martin_text.o -MF dep/martin_text.o.d  -c  ../martin_text.c
../martin_text.c: In function `main':
../martin_text.c:57: error: 'for' loop initial declaration used outside 
C99 mode
make: *** [martin_text.o] Error 1

Ich habe statt dem for ein while benutzt
1
for (;;)
2
{
3
    char text[] = "HelloAVR";
4
    text[0]='H';
5
    text[7]='R';
6
#if 0
7
    for(int ci=0; text[ci] != '\0'; ++ci)
8
    {
9
        putch(text[ci]);
10
    }
11
#else
12
    {
13
  int ci = 0;
14
  while(text[ci] != '\0')
15
  {
16
    putch(text[ci]);
17
    ci += 1;
18
  }
19
    }
20
#endif
21
    putch('\n');
22
}

Damit funktioniert die Routine im AVR Simulator.

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Im Anhang die AVR Simulation mit korrektem Inhalt in UDR1.

von Stefan (Gast)


Lesenswert?

Der C99 Fehlermeldung bin ich nachgegangen und danach die Source wieder 
abgeändert:
1
#if 1
2
    {
3
        int ci;
4
        for(ci=0; text[ci] != '\0'; ++ci)
5
        {
6
            putch(text[ci]);
7
        }
8
    }
9
#else
10
    {
11
        int ci = 0;
12
        while(text[ci] != '\0')
13
        {
14
            putch(text[ci]);
15
            ci += 1;
16
        }
17
    }
18
#endif

Funktioniert im AVR Simulator auch.

von martin (Gast)


Lesenswert?

Hallo,

danke für die Mühe. Aber kannst du dir vorstellen, wo der Fehler sein 
kann?
Wenn ich jeden Buchstaben einzeln zuweise:

  char text[10];
  text[0]='H';
  text[1]='e';
  text[2]='l';
  text[3]='l';
  text[4]='o';
  text[5]='A';
  text[6]='V';
  text[7]='R';
  text[8]='\0';

geht es auch: HelloAVR

Es liegt also an der Zuweisung: char text[] = "HelloAVR";
:confused:

MFG
Martin

von Stefan (Gast)


Lesenswert?

Ich kann im Moment nicht live auf einem Atmega128 testen. Läuft dein 
Projekt im AVR Simulator und kannst du das Fehlverhalten dort auch 
beobachten?

Ich kann den Fehler provozieren, wenn ich den falschen AVR Typ im AVR 
Studio einstelle (beim AVR Simulator und/oder im Projekt).

Bitte kontrolliere deine Projekteinstellungen zum Prozessortyp beim 
Kompilieren.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hab' mir einen ATmega128 in den STK gesteckt und die Baudrate auf 9600
geändert, weil das gerade mein angeklemmtest Terminal macht:
1
loAVR
2
     HelloAVR
3
             HelloAVR
4
                     HelloAVR
5
                             HelloAVR
6
                                     HelloAVR
7
                                             HelloAVR
8
                                                     HelloAVR
9
                                                             HelloAVR
10
                                                                     HelloAVR
usw. usf.

Da du offenbar Probleme mit den initialisierten Daten hast, vermute ich
die Ursache eher in deinem avr-objcopy-Kommando.

(Ich habe deine zweite Version genommen, mit -std=gnu99 compiliert auf
einem AVR-GCC 4.1.1.)

von martin (Gast)


Lesenswert?

Hallo,

meine Optionen:

Compiler:
avr-gcc -c -fmessage-length=0 -Wall -Wstrict-prototypes 
-I/usr/avr/include -mmcu=atmega128 -minit-stack=__stack -O0 
-fshort-enums -fpack-struct -funsigned-char -funsigned-bitfields 
-std=gnu99 -g2

Linker:
-lm -Wl,-Map=$(@:%.elf=%.map) --cref --oformat=elf32-avr

Objectcopy:
avr-objcopy -O ihex HelloAVR.elf HelloAVR.hex

MFG

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Im AVRSimulator läuft es auch mit diesen Optionen. Ich habe das Projekt 
gepackt und angefügt, vielleicht ist das "funktionierende" HEX-File 
interessant für dich. Toolchain war WinAVR-20060125 aus AVRStudio heraus 
bedient. Bei mir heisst das Projekt anders. Leider kann man damit nur 
auf ASM-Ebene in AVRStudio debuggen. Ich habe es auf die Schnelle nicht 
geschafft, das externe Makefile so anzupassen, dass AVRStudio die 
C-Source akzeptiert. Aber das bisschen ASM-Code hat man auch schnell so 
im Blick.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dein Hexfile funktioniert auch auf einem realen ATmega128.

von Stefan (Gast)


Lesenswert?

> Ich habe es auf die Schnelle nicht geschafft, das externe Makefile so
> anzupassen, dass AVRStudio die C-Source akzeptiert.

Hab's raus: Es ist ein schädlicher Zeilenumbruch in der Zeile mit den 
CFGLAS drin ;-) Das muss alles in eine Zeile... Jetzt geht in diesem 
Projekt auch Debugging auf C-Source Ebene in AVRStudio.

Merke: Makefiles nicht mit beliebigen Editoren bearbeiten! Wenn der 
Editor auf automatische Zeilenumbrüche eingestellt ist oder Tabs in 
Leerzeichen wandelt oder \n zu \r\n macht, kann es schwer auffindbaren 
Ärger geben...

von Stefan (Gast)


Lesenswert?

s/CFGLAS/CFLAGS/ ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Alles sowas sollte ein Editor ja auch nicht machen...

Zeilen im Makefile kann man umbrechen, indem man am Ende ein \
notiert (aber dann direkt danach das Newline!).

von martin (Gast)


Lesenswert?

Hallo,

danke euch! Das Hex File läuft bei mir auch.

Nur weiß ich leider immer noch nicht wie ich es selbst compilieren kann.

Deine AVRStudio-Files kann ich leider nicht gebrauchen, da ich unter 
LINUX arbeite. Aber wenn die Flags so auch bei dir gehen, kann das ja 
der Fehler auch nicht sein.

wisst ihr vielleicht noch eine "Schraube" an der ich drehen kann?

Danke und Grüße
Martin

von Stefan (Gast)


Lesenswert?

Macht deine Toolchain unter Linux auch die *.lss und *.map Dateien? Wie 
sehen die im Vergleich zur funktionierenden Version aus?

Aus dem Listing (*.lss) kann man sehen wie char text[] gefüllt wird und 
aus dem Map-File (*.map), wo die Daten herkommen.

Bei deinem Programm stammt "HelloAVR" ja aus dem FLASH-ROM, wird von 
dort von __do_copy_data ins SRAM kopiert (.data Bereich zwischen 
__data_start und __data_end) und wird dann in main() über Register auf 
den Stack kopiert.

Wie Jörg schon schrieb, ist da irgendwas faul.

Was findest du vielleicht anhand der funktionierenden Variante heraus.

Achtung: Ich habe allerdings noch zwei globale char Variablen vom 
Debuggen her im Programm vergessen. Die Zuweisungen sind zwar 
auskommentiert, aber der Platz wird noch angelegt.

von martin (Gast)


Lesenswert?

Die Dateien werden auch generiert. Das werde ich mir mal anschauen!

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.