Forum: Compiler & IDEs too many arguments to function `fdevopen'


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Stefan (Gast)


Lesenswert?

Hallo,

ich versuche gerade, den Code für den Webserver von Ulrich Radig zu 
übersetzen 
(http://mikrocontroller.cco-ev.de/php/counter/counter.php?datei=SourceCodeCPP_V1_40_IB.zip&location=http://mikrocontroller.cco-ev.de/files&type=count).

Ich benutze WinAVR 20070122 und bekomme beim Compilieren folgenden 
Fehler:
1
avr-gcc (GCC) 3.4.6
2
Copyright (C) 2006 Free Software Foundation, Inc.
3
This is free software; see the source for copying conditions.  There is NO
4
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5
6
7
Compiling: uart.c
8
avr-gcc -c -mmcu=atmega32 -I. -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=uart.lst  -std=gnu99 uart.c -o uart.o
9
In file included from main.h:17,
10
                 from uart.c:8:
11
C:/Programme/WinAVR/avr/include/avr/signal.h:36:2: warning: #warning "This header file is obsolete.  Use <avr/interrupt.h>."
12
In file included from main.h:23,
13
                 from uart.c:8:
14
rtl8019.h:84:1: warning: "ISR" redefined
15
In file included from main.h:16,
16
                 from uart.c:8:
17
C:/Programme/WinAVR/avr/include/avr/interrupt.h:96:1: warning: this is the location of the previous definition
18
uart.c: In function `UART_Init':
19
uart.c:36: warning: passing arg 1 of `fdevopen' from incompatible pointer type
20
uart.c:36: error: too many arguments to function `fdevopen'
21
make: *** [uart.o] Error 1

Das hat vor ca. 1,5 Jahren mit der Version 1.38 und der damalig 
aktuellen Version von WinAVR auch schon mal funktioniert.

Also habe ich die beiden alten Stände wieder reaktiviert und siehe da: 
gleicher Fehler!!!

Kann mir jemand sagen, wo hier das Problem liegt?

Stefan

von Joe (Gast)


Lesenswert?


von Stefan (Gast)


Lesenswert?

@Joe:
Also irgendwie ist mir noch nicht ganz klar, was das mit meinem Problem 
zu tun hat???

Sollte man statt "fdevopen" lieber "fdev_setup_stream" verwenden?

Aber der Code wurde doch früher schon einmal ohne Probleme übersetzt!?

von Joe (Gast)


Lesenswert?

int uart_putchar(char c, FILE *stream)
{
  while( !( UCSR0A & (1<<UDRE0)));
  UDR0 = c;

  return 1;
}

In der neuen Version werden nur 2 Argumente übergeben.

fdevopen (uart_putchar, NULL);

Alles klar ?

von Stefan (Gast)


Lesenswert?

> uart.c:36: warning: passing arg 1 of `fdevopen' from incompatible pointer type

Das erste Argument von fdevopen() muss int(*)(char, FILE *) sein.

Ändere uart_putchar z.b. in:
1
int uart_putchar (char c, FILE *dummy)
2
{
3
   // ...
4
}

> uart.c:36: error: too many arguments to function `fdevopen'

Hängt wohl folgendem define in main.h zusammen:
1
#define __STDIO_FDEVOPEN_COMPAT_12  // use old implementation of fdevopen

Der passende Prototyp hat dann drei Argumente, während bei 
nichtdefiniertem Switch nur zwei Argumente da sind. S. stdio.h von 
avr-libc
1
#if defined(__STDIO_FDEVOPEN_COMPAT_12)
2
/*
3
 * Declare prototype for the discontinued version of fdevopen() that
4
 * has been in use up to avr-libc 1.2.x.  The new implementation has
5
 * some backwards compatibility with the old version.
6
 */
7
extern FILE *fdevopen(int (*__put)(char), int (*__get)(void),
8
                      int __opts __attribute__((unused)));
9
#else  /* !defined(__STDIO_FDEVOPEN_COMPAT_12) */
10
/* New prototype for avr-libc 1.4 and above. */
11
extern FILE *fdevopen(int (*__put)(char, FILE*), int (*__get)(FILE*));
12
#endif /* defined(__STDIO_FDEVOPEN_COMPAT_12) */

Im Moment sieht es so aus, dass in main.h __STDIO_FDEVOPEN_COMPAT_12 
definiert ist (3-argumentiger Prototyp) und in uart.c die Funktion mit 
auch mit drei Argumenten benutzt wird, ABER der GCC annimmt, dass es nur 
2 Argumente gibt, entsprechend dem neuen Prototypen.

Irgendwie ist __STDIO_FDEVOPEN_COMPAT_12 verloren gegangen. Ich komme 
aber nicht drauf wo. Vielleicht Pfadprobleme mit den Includes? Oder es 
ist ein Folgefehler auf die Warnung hin.

von Stefan (Gast)


Lesenswert?

Ich sehe es gerade beim Korrekturlesen - die Warnung ist schon ein Indiz 
dafür, dass GCC den neuen Prototypen kennt bzw. das #define 
__STDIO_FDEVOPEN_COMPAT_12 aus main.h bei der Verarbeitung von stdio.h 
und uart.c nicht berücksichtigt wird. Dein uart_putchar() mit einem 
Argument passt sehr wohl zum alten Prototypen.

von Stefan (Gast)


Lesenswert?

Also ich habe das erstmal so geändert, wie Joe geschrieben hat. Dann 
treten aber weitere Fehler auf...

Ich habe aber jetzt keine Zeit nach den Ursachen zu suchen. 
Wahrscheinlich sind im Laufe der Updates von WinAVR mal wieder eine 
Menge Dinge umdefiniert worden.  :(  Und jedesmal muss man seine alten 
funktionierenden (!) Quellen wieder anpassen!

Ich bin jetzt auf die Version WinAVR-20050214 zurückgegangen und damit 
kann ich erstmal alles ohne Fehler compilieren. Das genügt mir zunächst.

Danke an alle.

von Stefan (Gast)


Lesenswert?

Die Funktion deiner Quellen hängt essentiell davon ab, dass das von dir 
in main.h definierte __STDIO_FDEVOPEN_COMPAT_12 beim include in stdio.h 
berücksichtigt wird.

Die einfachste Untersuchung auf Änderungen bei WinAVR wäre, dort 
nachzusehen, ob genau diese Stelle wie erwartet vorhanden ist. In 
avr-libc 1.4.5 habe ich nachgesehen; dort steht es noch drin. In WinAVR 
kann ich erst heute abend nachsehen.

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


Lesenswert?

Es ist genau diese eine Inkompatibilität (die Änderung der Anzahl und
des Typs der Argumente zu fdevopen()), die den Sprung von avr-libc
1.2.x nach 1.4.x verursacht hat.  Die wesentliche Motivation dafür war
übrigens nicht, das letztlich doch nie benutzte dritte Argument zu
fdevopen() zu entfernen, sondern vielmehr dass die Backend-Funktionen
(also put und get) jetzt noch den Zeiger auf den Stream mit
durchgereicht bekommen.  Damit können sie zusammen mit
fdev_set_udata() und fdev_get_udata() beliebige Anpassungen innerhalb
der Backend-Funktionen realisieren.  Um nur eine mögliche Variante zu
nennen: man muss für einen Controller mit 4 UARTs (ja, sowas gibt's
auch bei AVR ;-) nicht vier verschiedene Sätze von Funktionen
schreiben, sondern kann die Basisadresse der zu benutzenden UART als
"user data" an den Stream dranhängen.

Um die Inkompatibilität abzufedern wurder einerseits der 1.2er Branch
noch eine ganze Weile weitergepflegt (sorry, wenn Eric Weddington in
WinAVR nicht mehrere Versionen einer Komponente parallel verwalten
kann/möchte, kann ich auch nichts dafür), und zweitens wurde die
Möglichkeit geschaffen, durch Definition von
__STDIO_FDEVOPEN_COMPAT_12 vor dem include von <stdio.h> den alten
Prototypen stattdessen zu benutzen.  Damit ist man bis auf die eine
Zeile für dieses #define sourcecodekompatibel zu avr-libc 1.2.x (das
#define kann man ja sogar als -D-Option ins Makefile aufnehmen, dann
muss man den Sourcecode gar nicht anfassen).  Damit das funktioniert,
habe ich übrigens gegenüber dem ursprünglichen Patch für die user data
die Reihenfolge der Argumente in den Backend-Funktionen noch
getauscht.

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

> Ich benutze WinAVR 20070122 und bekomme beim Compilieren folgenden
> Fehler:
>
> avr-gcc (GCC) 3.4.6
> ...

Da stimmt was nicht. WinAVR 20070122 benutzt avr-gcc 4.1.1. Sorry, dass 
ich das jetzt erst sehe.

Ich habe mit dem "richtigen" WinAVR 20070122 das Projekt ohne Änderung 
übersetzen können. Falls es interessiert ist die Ausgabe von "make all" 
im Anhang.

Vielleicht noch ein Tipp:

Ich habe auch zwei WinAVR parallel installiert. Das aktuelle liegt im 
Ordner d:\WinAVR, das andere im Ordner d:\WinAVR-20060125. Wenn ich 
tauschen will, benenne ich die Ordner entsprechend um. d:\WinAVR wird zu 
d:\WinAVR-20070122 und d:\WinAVR-20060125 wird zu d:\WinAVR. Am Pfad 
ändere ich nix. Mit symbolischen Links wäre das noch schöner zu lösen, 
leider kenne ich keine Link-Lösung für Windows98SE.

von Stefan (Gast)


Lesenswert?

Ähm, bevor Verwirrung aufkommt: Die letzte Nachricht hat der 
Antworter-Stefan geschrieben, nicht der OP-Stefan. OP-Stefan sollte 
seine WinAVR Installation checken.

von Stefan (Gast)


Lesenswert?

Ähm, noch was aus deinem make-Lauf

> avr-gcc -c -mmcu=atmega32 -I. -g -Os -funsigned-char -funsigned-bitfields 
-fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=uart.lst 
-std=gnu99 uart.c -o uart.o

Ich habe das makefile genommen wie es unter dem von dir angegebenen Link 
steht. Das ist für den Atmega644.

Wenn ich Atmega32 im makefile setze, kommt als erstes ein Fehler in 
clock.c, dass TIMSK1 undefiniert ist. Der Atmega32 hat nur ein TIMSK.

Wenn man an der Stelle in clock.c nach sieht, erkennt man, dass die 
Source brutale Änderungen (ohne #if/#endif o.ä.) für den Atmega644 
enthält. Ich habe nicht weiter nachgesehen, ob man das auf den Atmega32 
zurückpatchen könnte.

Du solltest also zusätzlich deinen Projektbaum kontrollieren, ob die 
noch mit den oben angegebenen Sourcen übereinstimmen bzw. wir 
diskutieren die ganze Zeit über zwei verschiedene Sourcen ;-(

von Stefan (Gast)


Lesenswert?

@Stefan:

Stimmt. Du hast vollkommen Recht!

Die Angabe der GCC-Version sehe ich nicht ganz so problematisch, da ich 
mit mehreren Versionen "gespielt" habe und immer der gleiche Fehler 
auftrat.

Ich habe jetzt noch einmal von allem das Aktuellste genommen, und siehe 
da: Es geht!

Keine Ahnung, warum es beim 1. Mal nicht ging?????

Vielen Dank.

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.