Forum: Compiler & IDEs AVR-GCC-Eclipse: printf("H") klappt, printf("Ha") klappt nicht!


von Tobias H. (the)


Lesenswert?

Hallo!

Ich habe bisher kleinere Programme mit AVR-Studio progammiert und möchte 
nun auf Eclipse umsteigen (AVR-Plugin).

Da GANZ einfache Programme schnell zum Laufen zu bekommen waren, habe 
ich nun ein kleines Programm geschrieben, dass in einer Endlosschleife 
Buchstaben auf ein RS232-Terminal ausgibt.

Und jetzt kommt das Problem:
Mit dem von Eclipse erzeugten HEX-File funktioniert die Ausgabe von 
EINZELBUCHSTABEN mit printf("H") (beispielsweise) problemlos (natürlich 
auch in ARV-Studio).
Ändere ich diese Ausgabe in printf("Ha") (also mehrere Buchstaben) 
klappt es unter Eclipse NICHT MEHR, unter AVR-Studio schon.

Der C-Code ist (natürlich) in beiden Fällen gleich!

Daher kann es eigentlich nur an den (diversen) IDE-Einstellungen liegen 
[dieses Problem hat man ja eigentlich immer, wenn man die IDE wechselt].

Was mir auffällt ist, dass Eclipse mit avr-g++ kompiliert (obwohl mein 
Program unter Main.c gespeichert ist) und AVR-Studio mit avr-gcc (wobei 
ich noch nicht sehe, wo dabei das Problem sein könnte).

Vielleicht kann einer von Euch mir da weiter helfen? Anbei findet Ihr 
die beiden Makefiles.

Lieben Dank!

P.S.: Sorry für den langen Anhang aber ich war irgendwie nicht in der 
Lage, zwei Dateien anzuhängen... und auf das Entpacken eines .zip hat 
wahrscheinlich keiner Lust ;-)

Eclipse_makefile:
1
################################################################################
2
# Automatically-generated file. Do not edit!
3
################################################################################
4
5
-include ../makefile.init
6
7
RM := rm -rf
8
9
# All of the sources participating in the build are defined here
10
-include sources.mk
11
-include subdir.mk
12
-include source/subdir.mk
13
-include objects.mk
14
15
ifneq ($(MAKECMDGOALS),clean)
16
ifneq ($(strip $(C++_DEPS)),)
17
-include $(C++_DEPS)
18
endif
19
ifneq ($(strip $(C_DEPS)),)
20
-include $(C_DEPS)
21
endif
22
ifneq ($(strip $(ASM_DEPS)),)
23
-include $(ASM_DEPS)
24
endif
25
ifneq ($(strip $(CC_DEPS)),)
26
-include $(CC_DEPS)
27
endif
28
ifneq ($(strip $(CPP_DEPS)),)
29
-include $(CPP_DEPS)
30
endif
31
ifneq ($(strip $(S_DEPS)),)
32
-include $(S_DEPS)
33
endif
34
ifneq ($(strip $(CXX_DEPS)),)
35
-include $(CXX_DEPS)
36
endif
37
ifneq ($(strip $(C_UPPER_DEPS)),)
38
-include $(C_UPPER_DEPS)
39
endif
40
ifneq ($(strip $(S_UPPER_DEPS)),)
41
-include $(S_UPPER_DEPS)
42
endif
43
endif
44
45
-include ../makefile.defs
46
47
# Add inputs and outputs from these tool invocations to the build variables 
48
LSS += \
49
AVR_COBOLT.lss \
50
51
FLASH_IMAGE += \
52
AVR_COBOLT.hex \
53
54
EEPROM_IMAGE += \
55
AVR_COBOLT.eep \
56
57
SIZEDUMMY += \
58
sizedummy \
59
60
61
# All Target
62
all: AVR_COBOLT.elf secondary-outputs
63
64
# Tool invocations
65
AVR_COBOLT.elf: $(OBJS) $(USER_OBJS)
66
  @echo 'Building target: $@'
67
  @echo 'Invoking: AVR C++ Linker'
68
  avr-g++ -Wl,-Map,AVR_COBOLT.map,--cref -Wl,-u,vfprintf -lprintf_flt -lm -lc -lm -L"C:\WinAVR-20081205\avr\lib\avr6" -mmcu=atmega640 -o"AVR_COBOLT.elf" $(OBJS) $(USER_OBJS) $(LIBS)
69
  @echo 'Finished building target: $@'
70
  @echo ' '
71
72
AVR_COBOLT.lss: AVR_COBOLT.elf
73
  @echo 'Invoking: AVR Create Extended Listing'
74
  -avr-objdump -h -S AVR_COBOLT.elf  >"AVR_COBOLT.lss"
75
  @echo 'Finished building: $@'
76
  @echo ' '
77
78
AVR_COBOLT.hex: AVR_COBOLT.elf
79
  @echo 'Create Flash image (ihex format)'
80
  -avr-objcopy -R .eeprom -O ihex AVR_COBOLT.elf  "AVR_COBOLT.hex"
81
  @echo 'Finished building: $@'
82
  @echo ' '
83
84
AVR_COBOLT.eep: AVR_COBOLT.elf
85
  @echo 'Create eeprom image (ihex format)'
86
  -avr-objcopy -j .eeprom --no-change-warnings --change-section-lma .eeprom=0 -O ihex AVR_COBOLT.elf  "AVR_COBOLT.eep"
87
  @echo 'Finished building: $@'
88
  @echo ' '
89
90
sizedummy: AVR_COBOLT.elf
91
  @echo 'Invoking: Print Size'
92
  -avr-size --format=avr --mcu=atmega640 AVR_COBOLT.elf
93
  @echo 'Finished building: $@'
94
  @echo ' '
95
96
# Other Targets
97
clean:
98
  -$(RM) $(OBJS)$(C_DEPS)$(EEPROM_IMAGE)$(ELFS)$(FLASH_IMAGE)$(LSS)$(S_DEPS)$(CXX_DEPS)$(S_UPPER_DEPS)$(C++_DEPS)$(ASM_DEPS)$(CC_DEPS)$(CPP_DEPS)$(C_UPPER_DEPS)$(SIZEDUMMY) AVR_COBOLT.elf
99
  -@echo ' '
100
101
secondary-outputs: $(LSS) $(FLASH_IMAGE) $(EEPROM_IMAGE) $(SIZEDUMMY)
102
103
.PHONY: all clean dependents
104
.SECONDARY:
105
106
-include ../makefile.targets


AVR-Studio_makefile:
1
###############################################################################
2
# Makefile for the project AVR_COBOLT
3
###############################################################################
4
5
## General Flags
6
PROJECT = AVR_COBOLT
7
MCU = atmega640
8
TARGET = AVR_COBOLT.elf
9
CC = avr-gcc
10
11
## Options common to compile, link and assembly rules
12
COMMON = -mmcu=$(MCU)
13
14
## Compile options common for all C compilation units.
15
CFLAGS = $(COMMON)
16
CFLAGS += -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
17
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d 
18
19
## Assembly specific flags
20
ASMFLAGS = $(COMMON)
21
ASMFLAGS += $(CFLAGS)
22
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
23
24
## Linker flags
25
LDFLAGS = $(COMMON)
26
LDFLAGS +=  -Wl,-Map=AVR_COBOLT.map
27
28
29
## Intel Hex file production flags
30
HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
31
32
HEX_EEPROM_FLAGS = -j .eeprom
33
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
34
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings
35
36
37
## Libraries
38
LIBS = -lm 
39
40
## Objects that must be built in order to link
41
OBJECTS = Main.o 
42
43
## Objects explicitly added by the user
44
LINKONLYOBJECTS = 
45
46
## Build
47
all: $(TARGET) AVR_COBOLT.hex AVR_COBOLT.eep AVR_COBOLT.lss size
48
49
## Compile
50
Main.o: ../Main.c
51
  $(CC) $(INCLUDES) $(CFLAGS) -c  $<
52
53
##Link
54
$(TARGET): $(OBJECTS)
55
   $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
56
57
%.hex: $(TARGET)
58
  avr-objcopy -O ihex $(HEX_FLASH_FLAGS)  $< $@
59
60
%.eep: $(TARGET)
61
  -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
62
63
%.lss: $(TARGET)
64
  avr-objdump -h -S $< > $@
65
66
size: ${TARGET}
67
  @echo
68
  @avr-size -C --mcu=${MCU} ${TARGET}
69
70
## Clean target
71
.PHONY: clean
72
clean:
73
  -rm -rf $(OBJECTS) AVR_COBOLT.elf dep/* AVR_COBOLT.hex AVR_COBOLT.eep AVR_COBOLT.lss AVR_COBOLT.map
74
75
76
## Other dependencies
77
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)

von Michael H. (mah)


Lesenswert?

und wo ist das Program, Ha?

-Michael

von Tobias H. (the)


Lesenswert?

Hmm, dachte, dass interessiert niemanden, da es ja in beiden Fällen 
identisch ist...

Aber kein Problem, kommt.

Danke schonmal für die schnelle Antwort!
1
// ============================ USART-Test for ATmega48 on STK500 valuation-board ===
2
3
#ifndef F_CPU
4
#define F_CPU 4000000 //Quarz frequency in Hz. Insert actual value!!
5
#endif
6
7
#include <stdio.h>
8
9
//our own inlcude files:
10
#include "Usart.h"
11
#include "I2c.h"
12
#include "Adc.h"
13
14
// ===============================================================
15
//  BEGIN OF MAIN PROGRAMM
16
// ===============================================================
17
18
int main(void)
19
{
20
  stdin = stdout = fdevopen(usartPutc, usartGetcNowait);
21
  usartInit();
22
  adcInit();
23
24
  DDRJ = 0xFF;
25
  PORTJ = 0xFF;
26
27
  //to give some visible feedback to the user, that the software update was successful:
28
  //TODO: Extract the following to a function inside GeneralAtmelMcu.h
29
  _delay_ms(1000);
30
  PORTJ = 0x00;
31
  _delay_ms(1000);
32
  PORTJ = 0x01;
33
34
  while(1) {
35
    printf("Ha");
36
    _delay_ms(10);
37
    //printf("Hallo Welt!");
38
  }
39
40
  return 0;
41
}

von Michael H. (mah)


Lesenswert?

einmal gehts noch - usart.h bitte. Und woher sind usartPutc & 
usartGetcNowait?

Ihr erwartet immer Hilfe und benehmt Euch dabei wie verlegene 
Verdächtige, denen man erstmal die Tatsachen abpressen muss..

-mah

von Nicolas S. (Gast)


Lesenswert?

Kann das usartPutc ganze Strings oder nur chars ?

von Tobias H. (the)


Lesenswert?

;-)

Ich habe gar kein schlechtes Gewissen! Denke nur (nach wie vor), dass 
der Fehler nicht im CODE liegen kann, da es ja im AVR-Studio läuft, nur 
halt unter Eclipse nicht => Makefile-Unterschiede.

Aber klar, könnt Ihr den Code sehen:
1
#ifndef USART_H
2
#define USART_H
3
4
//TODO: Add comments for this class
5
6
#include <avr/interrupt.h>
7
8
#include "GeneralAtmelMcu.h"
9
#include "ErrorHandling.h"
10
11
12
// ================== Definitions for UART ================================
13
// from   uart.h ==========
14
15
16
#define UART_BAUD_RATE 9600L
17
#define UART_BAUD_CALC ((F_CPU)/((UART_BAUD_RATE)*16L)-1)
18
19
#define RING_BUFFER_LENGTH 20 //bufferlength for serial receive  /  Pufferlänge für seriellen Empfang
20
21
22
volatile unsigned char ringBuffer[RING_BUFFER_LENGTH];    // Ringbuffer
23
volatile uint8_t
24
                 ringBufferPosition,   // Position to read next / die als nächstes gelesen werden muß im Ringpuffer
25
             ringBufferCounter,   // Number of Char to read / Anzahl zu lesender Zeichen im Puffer
26
             udrData;   // Data from UART / Daten aus dem UART
27
                    // (volatile, to prevent removal by opimizer / Präprozessor)
28
29
30
31
32
33
34
void usartInit()
35
{
36
  /* Set baud rate */
37
  UBRR1H = (unsigned char)(UART_BAUD_CALC>>8);
38
  UBRR1L = (unsigned char) UART_BAUD_CALC;
39
40
  /* Enable receiver and transmitter */
41
  UCSR1B =  (1<<TXEN1);   // UART TX (send) enable
42
  UCSR1B |= (1<<RXEN1);   // UART RX (receive) enable
43
  UCSR1B |= (1<<RXCIE1);  // Interrupt on receive enable
44
  sei();                  // enable global Interrupt
45
46
    /* Set frame format: 8data, 2stop bit */
47
    UCSR1C = (1<<USBS1)|(3<<UCSZ10);
48
}
49
50
51
52
// send ONE character  // Ein Zeichen senden
53
int16_t usartPutc(char c, FILE* notused)
54
{
55
    while(!(UCSR1A & (1 << UDRE1)));     // wait until USART send register ready / warte, bis UDR bereit
56
57
    UDR1 = c;                // send caracter / sende Zeichen
58
    //  _delay_ms(2);
59
    return 0;
60
}  // end of usartPutc
61
62
63
64
// Interruptroutine, for immediate reading of one character from UART, if receive complete
65
ISR(USART1_RX_vect)
66
{
67
  udrData= UDR1;   //get byte in any case to prevent endless interrupt
68
69
  if(ringBufferCounter < RING_BUFFER_LENGTH)   // do not write to buffer it full / keinen Zeichen in einem vollen Ringpuffer überschreiben
70
  {
71
      ringBuffer[(ringBufferPosition+ringBufferCounter++) % RING_BUFFER_LENGTH] = udrData;  // which position? / welche Position?
72
                // Gelesene Zeichenpos + Anzahl Zeichen MODULO Pufferlänge
73
         // (von 0 wieder anfangen, wenn Ende erreicht)
74
        // >> LESBARER UMSCHREIBEN !!!!!!!!!!!!!!!!!!!!!!!!!!!
75
    }
76
  else   // if buffer was full set error flag
77
  {
78
       throwError(ERROR_USART_RINGBUFFER_FULL);
79
  }
80
}
81
82
83
84
int16_t  usartGetcNowait (FILE* notused)  // read ONE char from ringbuffer, use int16_t for errorhandling (errors are -1 or -2)
85
{
86
  unsigned char c;
87
88
  if(ringBufferCounter)        // if there are one or more characters in ringbuffer ...
89
  {
90
     cli();    // disable interrupthandling (to prevent disturbing ringbuffer writeroutine)
91
92
93
     c = ringBuffer [ringBufferPosition++];  // get next character ...
94
     ringBufferCounter--;              // and decrement counter (numbers of unread characters)
95
96
     if (ringBufferPosition >= RING_BUFFER_LENGTH)  ringBufferPosition = 0;  // if last position in ringbuffer
97
                                  // set buffer position pointer to 0
98
99
     sei();                  // enable interrupthandling
100
101
       if (c == 0x04)    // if End Of File  (ASCII-Code 0x04)
102
     {
103
        //return _FDEV_EOF;   // return error code -2 = end of file
104
     }
105
106
    }        // end of "if(ringBufferCounter)"
107
  else                         // if ringbuffer is empty, i.e. nothing to read
108
  {                            // do NOT wait until there is a character in buffer
109
                 // but return an error code
110
       throwError(ERROR_USART_RINGBUFFER_EMPTY);
111
     return _FDEV_ERR;         // return error code -1 = transmission error
112
    }
113
114
/*       if (ringBufferCounter < 10)      // if buffer gets nearly full: set
115
hardware handshake for CTS / "Busy"
116
  {
117
    // ----------------------------------------- ALLES NICHT GÜLTIG !!!!
118
PORT ÄNDERN !!! ---------------
119
    PORTD &=  ~(1<<PD2);  // PD2 = CTS (Busy) 0 = start TxD from VDIP2
120
      _delay_ms(1);
121
    PORTD |=   (1<<PD2);  // PD2 = CTS (Busy) 1 = stopp TxD from VDIP2
122
    }
123
  else
124
    {
125
    PORTD |=   (1<<PD2);  // PD2 = CTS (Busy) 1 = stopp TxD from VDIP2
126
    }
127
*/
128
129
   return (c);        // Zeichen zurückgeben
130
}
131
132
#endif //USART_H

Die putc()-Funktion kann nur jeweils nur einen Character senden (denke 
das ist auch allgemein so üblich). Printf() ruft dann für jeden char die 
angegebene putc() auf.

von Simon K. (simon) Benutzerseite


Lesenswert?

Tobias H. wrote:
> Da GANZ einfache Programme schnell zum Laufen zu bekommen waren, habe
> ich nun ein kleines Programm geschrieben, dass in einer Endlosschleife
> Buchstaben auf ein RS232-Terminal ausgibt.

Alles klar, unter einfach versteh ich aber was anderes.

Du hast ja Ringbuffer und Printf Unterstützung eingebaut. Versuch doch 
mal erst mal mit einer normalen Schreibfunktion und grenze den Fehler 
ein.

von Tobias H. (the)


Lesenswert?

Argh, sorry, aber das ist einer der Gründe dafür gewesen, dass ich das 
Programm ursprünglich NICHT posten wollte.

DENN: wenn man mal hinsieht, verwende ich Ringbuffer, etc. in meinem 
main gar nicht! Die einzigen Funktionen, aus der Uart.h, die in meinem 
main aufgerufen werden, sind init() und putc(), der Rest NICHT. Daran 
kann es also nicht liegen. (Ich hätte den Rest gar nicht zeigen 
sollen...)

Und ausserdem funktioniert das alles unter AVR-Studio wunderbar! Die 
Frage ist und bleibt, warum es in Eclipse nicht läuft, bzw. warum nur 
mit einzelnen Buchstaben.

Also nochmal: Woran könnte es liegen, dass IDENTISCHER Code unter 
AVR-Studio auf dem Controller anständig läuft und unter Eclipse eben 
nicht? Meiner Meinung nach kann es nur an den Makefiles liegen (s.o.)?

von Simon K. (simon) Benutzerseite


Lesenswert?

Tobias H. wrote:
> Argh, sorry, aber das ist einer der Gründe dafür gewesen, dass ich das
> Programm ursprünglich NICHT posten wollte.
Hä? Bleib mal auf dem Teppich.

> DENN: wenn man mal hinsieht, verwende ich Ringbuffer, etc. in meinem
> main gar nicht!
Na klar, Printf ruft die Ringbuffer Funktionen auf.

> Und ausserdem funktioniert das alles unter AVR-Studio wunderbar! Die
> Frage ist und bleibt, warum es in Eclipse nicht läuft, bzw. warum nur
> mit einzelnen Buchstaben.
Das hat zu 99% nichts mit AVR Studio oder Eclipse zu tun. Das ist nur 
ein Symptom, welches du siehst. Das Problem wird an einer 
unterschiedlichen Kommandozeile liegen und an Optionen, die beim 
Kompilieren mitgegeben werden. Dadurch tritt der Fehler zufällig einmal 
auf, und einmal nicht.

> Also nochmal: Woran könnte es liegen, dass IDENTISCHER Code unter
> AVR-Studio auf dem Controller anständig läuft und unter Eclipse eben
> nicht? Meiner Meinung nach kann es nur an den Makefiles liegen (s.o.)?
Ich vermute den Fehler in den Ringbuffer Funktionen. Wo hast du diese 
her? Sind die getestet? Ich habe mir die nicht angeschaut, aber ich 
schlage vor, dass du die erst mal raus machst und an FDEV_STREAM_SETUP 
eine ganz stinknormale uart_putc funktion reingibst.

Übrigens, was heißt "Funktioniert nicht"? Ich muss da Michael Haberler 
schon Recht geben, mit der Geheimniskrämerei kommt man nicht weit.
Wie gesagt: Fehler eingrenzen ist die Devise. Und zwar bei jedem Fehler, 
du kannst ja nicht bei jedem Fehler jemand anders fragen.

von Tobias H. (the)


Lesenswert?

Hallo Simon,

entschuldige bitte. Das "Argh" und so weiter war kein Vorwurf. Eher an 
mich gerichtet, weil ich den Code vorher hätte "filtern" sollten, um 
Mißverständissen vorzubeugen (ich will doch nix verheimlichen!).
Ich bin sehr dankbar für die Existenz solcher Foren und für die Hilfe, 
die einem von Forenteilnehmern gewährt wird.

Da ich mich offensichtlich unglücklich ausgedrückt habe, hier nochmal 
das Problem:

1. Der obige Code kompiliert unter AVR-Studio (mit dem avr-gcc) und 
Eclipse (hier mit dem avr-g++, weiß nicht, wie man das ändert) 
fehlerfrei.

2. Mit Hilfe des AVR-Studios habe ich meinen Controller programmiert und 
das Programm getestet (es macht ja nichts ausser einer sich endlos 
wiederholenden Ausgabe von "Ha" auf dem Hyperterminal eines 
angeschlossenen Rechners). So funktioniert es prima.

3. Meine Uart.h besteht schon seit ein paar Wochen und die darin 
enthaltenen Funktionen zum Empfangen von Daten habe ich auch schon 
genutzt (den Ringbuffer hat ein Kollege geschrieben...) und deren 
korrekte Funktion getestet.

4. Punkt 3 ist insofern irrelevant, als ich der Meinung bin, dass ausser 
den init() und putc() Funktionen KEINE weiteren Funktionen dieser Datei 
von meinem main aufgerufen werden. Soweit ich weiß, ruft printf() NICHT 
getc() oder eine andere, mit dem Empfangen von Daten verbundene Funktion 
auf. Natürlich kann ich da irren aber in dem Fall wäre ich für eine 
Erklärung dankbar, da dann etwas ganz anders läuft, als ich dachte.

5. Sobald ich den Code mit Eclipse kompiliere und dann auf den 
Controller programmiere, geht es schief und auf dem Terminal landet 
nichts mehr.

6. Ändere ich die printf("Ha")-Anweisung in printf("H"), so läuft das 
Programm wieder einwandfrei.

7. Da der Quellcode beider IDEs identisch ist, kann es nur an den 
IDE-Einstellungen liegen, aus denen ja in beiden Fällen das Makefile 
erstellt wird.
Dieses Makefile definiert die exakte Form der avr-gcc/avr-g++ 
Kommandozeile. Sind die Makefiles unterschiedlich, resultieren 
unterschiedliche Kommandozeilen und damit ergibt sich eine mögliche 
Fehlerursache.

Liebe Grüße und besten Dank für die Hilfe.

von Oliver (Gast)


Lesenswert?

>Sind die Makefiles unterschiedlich, resultieren
>unterschiedliche Kommandozeilen und damit ergibt sich eine mögliche
>Fehlerursache.

Schau dir die Compileraufrufe doch einfach an, dann weisst du, ob es da 
Unterschiede gibt. So viele Möglichkeiten gibt es da gar nicht. Kandidat 
ist z.B die signed oder unsigned-definition des Typs char. Wobei das 
nicht fest vorgegeben ist, sondern in den Settings bzw. Optionen 
eingestellt werden kann.

Sollte es allerdings daran liegen, liegt es trotzdem an deinem Programm. 
Das muß so geschrieben sein, daß es mit beiden Varianten funktioniert.

Oliver

von Tobias H. (the)


Lesenswert?

Stimme ich in beiden Punkten voll zu. Sobald ich morgen wieder an den 
Rechner komme, werde ich die Kommandozeilen mal vergleich und hier 
posten.

von Oliver (Gast)


Lesenswert?

Kompilieren lässt sich der Code nicht, da fehlt die Hälfte. Also such 
deine Fehler selber. In deinem Code, nicht in den makefiles. Die sind in 
Ordnung.

Und dann hinsetzten und tausendmal schreiben:
Ich soll keine .c-Files includen - auch nicht, wenn sie als headerfiles 
getarnt sind.

Oliver

von Oliver (Gast)


Lesenswert?

>Sobald ich morgen wieder an den
>Rechner komme, werde ich die Kommandozeilen mal vergleich und hier
>posten.

???

Die stehen doch in deinen makefiles.

Oliver

von Tobias H. (the)


Lesenswert?

Ich hatte halt gehofft, dass jemand das Problem kennt und direkt sieht: 
"ah, da musst du das Flag XY noch setzen". Will doch von niemandem 
verlangen, meinen Code zu kompilieren.

Da ich aber langsam einsehe, dass das vielleicht sogar der einfachere 
Weg ist, werde ich morgen ein minimalistisches und hoffentlich dann auch 
kompilier-/reproduzierbares Paket posten.

@header-Files: mea culpa. Sollte allerdings keinerlei Probleme machen, 
da der Compiler das meines Wissens nach einfach implizit "inlined". 
Warum es überhaupt soweit kam? Lange Geschichte, die was mit geerbtem 
Code zu tun hat... ;-)

von Simon K. (simon) Benutzerseite


Lesenswert?

Es gibt Namenskonflikte wenn du das Headerfile in mehreren .c Dateien 
inkludierst, da die Funktionen nicht static sind.

von Oliver (Gast)


Lesenswert?

>Lange Geschichte, die was mit geerbtem Code zu tun hat... ;-)

In der Zeit, in der du diesen Beitrag hier geschrieben hast, hättest du 
schon die UART-Funktionen in ein .c und ein .h aufteilen können. Die 
passende Struktur ist da ja schon drin. Mach das mal, dann sieht es 
gleich viel besser aus.

Oliver

von Thomas H. (innot)


Lesenswert?

Tobias H. wrote:

>
> Was mir auffällt ist, dass Eclipse mit avr-g++ kompiliert (obwohl mein
> Program unter Main.c gespeichert ist) und AVR-Studio mit avr-gcc (wobei
> ich noch nicht sehe, wo dabei das Problem sein könnte).

Tobias, Du hast, als Du das Projekt angelegt hast, (wahrscheinlich aus 
versehen) 'C++ Project' ausgewählt. Damit wird dann der C++ Linker 
anstatt des normalen C Linkers benutzt. Ob das was mit Deinem Problem zu 
tun hat weiß ich nicht, aber es kann nicht schaden das zu korrigieren. 
Dazu gibt es zwei Möglichkeiten:

1. Offizieller und sicherer weg: Neues 'C Project' anlegen, die Sourcen 
dorthin kopieren und die Einstellungen anpassen.

2. Inoffizieller 'Hack' (auf eigene Verantwortung): In der Datei 
'.project' im Projektverzeichnis die Zeile
1
<nature>org.eclipse.cdt.core.ccnature</nature>
löschen. Wichtig: nicht die Zeile mit cnature löschen, sondern nur die 
mit ccnature (zwei c am Anfang)

Anschließend Eclipse neu starten (oder das Projekt schließen und wieder 
öffnen).
Die Datei '.project' wird nur im "Navigator" angezeigt (Window->Show 
View->Navigator)

Thomas

von Tobias H. (the)


Lesenswert?

Hallo Thomas!

Entschuldige die späte Antwort, ich war auf Reisen.

Habe Deinen Rat beherzigt und aus dem Eclipse-C++-Projekt ein C-Projekt 
gemacht (gemäß Deinem "Hack"...).

Tatsächlich FUNKTIONIERT der Code dann auch unter Eclipse, unabhängig 
davon, wieviele Buchstaben man mit printf() sendet (zur Erinnerung: 
printf("H") funktionierte unter Eclipse UND AVR-Studio, printf("Ha") nur 
unter AVR-Studio)!

Insofern möchte ich mich ganz herzlich bei Dir aber auch allen anderen 
Hilfsbereiten Beantwortern bedanken!

Falls jemand dieses Verhalten näher untersuchen möchte, hier nochmal 
meine Main.c, in einer Version in der keine weiteren Dateien gebraucht 
werden (Atmega640):
1
// ============================ USART-Test for ATmega640 =========
2
3
#ifndef F_CPU
4
#define F_CPU 4000000 //Quarz frequency in Hz. Insert actual value!!
5
#endif
6
7
// baud rate calculation:
8
#define UART_BAUD_RATE 9600L
9
#define UART_BAUD_CALC ((F_CPU)/((UART_BAUD_RATE)*16L)-1)
10
11
#include <stdio.h>
12
#include <util/delay.h>
13
#include <avr/io.h>
14
15
16
// usart functions:
17
void usartInit()
18
{
19
  /* Set baud rate */
20
  UBRR1H = (unsigned char)(UART_BAUD_CALC>>8);
21
  UBRR1L = (unsigned char) UART_BAUD_CALC;
22
23
  /* Enable receiver and transmitter */
24
  UCSR1B =  (1<<TXEN1);   // UART TX (send) enable
25
  UCSR1B |= (1<<RXEN1);   // UART RX (receive) enable
26
27
    /* Set frame format: 8data, 2stop bit */
28
    UCSR1C = (1<<USBS1)|(3<<UCSZ10);
29
}
30
31
32
// send ONE character
33
int16_t usartPutc(char c, FILE* notused)
34
{
35
    while(!(UCSR1A & (1 << UDRE1)));     // wait until USART send register ready
36
37
    UDR1 = c;                // send caracter
38
39
    return 0;
40
}
41
42
43
int16_t  usartGetc(FILE* notused) //just a dummy
44
{
45
  return 'c';
46
}
47
48
49
// ===============================================================
50
//  BEGIN OF MAIN PROGRAMM
51
// ===============================================================
52
int main(void)
53
{
54
55
  stdin = stdout = fdevopen(usartPutc, usartGetc);
56
  usartInit();
57
58
  while(1) {
59
    //printf("H");  //if you put one letter like "H" it works (Both IDEs)
60
    printf("Ha");  //if you put more then one letter, like "Ha", it doesn't work under eclipse any more!
61
            //(it still works under AVR-Studio)
62
    _delay_ms(10);
63
  }
64
65
  return 0;
66
}

Da es ja prinzipiell möglich zu sein scheint, C++-Programme für den 
Atmega zu kompilieren, könnte es etwas mit extern "C" { ... } zu tun 
haben, wie auf der AVR-GCC-Wiki angedeutet?

Liebe Grüße

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.