hi
[projekt lcd display] - habe ein struct:
typedef struct {
uint16_t color;
} tSquare;
und eine zugehörige funktion
void ShowSquare(tSquare *pSquare) {
glcdSetFgColor(pSquare->color);
glcdRectangle(10,20,15,25);
}
in MAIN wird folgendes aufgerufen:
tSquare square;
square.color = BLUE; //BLUE ist definiert constante
ShowSquare(&square);
==> das rechteck wird nicht blau
auch wenn ich das struct nicht mittels pointer übergebe sondern per
value geht es nicht
KANN ES SEIN DASS DIE ÜBERGABE MITTELS STRUCT IM NEUEN WINAVR EINEN BUG
HAT (es wird ein default makefile verwendet) ?
falls ich BLUE direkt in der funktion glcdSetFgColor aufrufe, wird es
blau dargestellt
danke
Ein alignment - Problem? Die Felder eines structs werden vom Compiler
normalerweise (wegen des schnelleren Zugriffs) auf Maschinenwortbreite
ausgerichtet. Was ergibt sizeof(tSquare)? Mit 8 oder 16-Bit alignment
sollte 2 herauskommen, mit 32-Bit alignment kommt 4 heraus.
In diesem Fall würde ich das struct testweise anders definieren:
typedef struct {
uint16_t color2;
uint16_t color;
} tSquare;
und dann so testen:
tSquare square;
square.color = BLUE;
square.color2 = BLUE;
ShowSquare(&square);
ja
ich werde in den nächsten tagen nochmals die struct übergabe getretnnt
testen mit ausgabe über uart
scheint so dass diese nicht so richtig funktioniert - ich bekomme nicht
die werte des structs übergebene in der funktion.
Es sieht sehr nach Compiler-Bug aus. Interessant wäre vielleicht, in der
Routine Show-Square BLUE nochmal explizit zuzuweisen, also
pSquare->color=BLUE; vor dem Aufruf der lcd-Funktion, und wenn's dann
geht, vor dem Aufruf etwas einzubauen wie if (pSquare!=NULL); um den
Compiler zu zwingen den Pointer zu laden.
Schon klar. Es ging mir darum, das Problem einzugrenzen. Man könnte
(außer einem Bug-Report) als Workaround auch versuchen, einen pointer
auf einen pointer zu übergeben, also etwa tSquare **ppSquare.
nur nächstes problem,:
falls ich nun in der struct einen weiteren wert habe:
typedef struct {
uint16_t color;
uint8_t x;
} tSquare;
GEHT ES NICHT MEHR
folgender versuch schlägt auch fehl (koordinatenübergabe)
typedef struct {
uint8_t x;
uint8_t x;
} tSquare;
werde mal den alten winavr installieren
WAS SEHR INTERESSANTES HERAUSGEFUNDEN:
falls das struct global definiert wird, funktionierts nicht
falls es lokal definiert wird (innerhalb main) funktioniert es
einwandfrei...
wenn struct so kleingewichtig ist, dann kann man
auf den Zeiger verzichten und per value übergeben.
Wenn es dann geht, dann macht Compiler was falsch.
Allerdings ist das so ein typischer Fall, wie du
es gebrauchst, dass mir ein Bug eher unwahrscheinlicher scheint.
Ok, das ist C.
#define BLUE=10
müsste so heissen
#define BLUE 10
10 ist dann vom Typ int. Aber das nur nebenbei.
Ich vermute, dass im .c file keine Declaration
für die Funktion vorliegt und Compiler was falsches annimt.
Das ist C wie gesagt :)
Kannst du den Compiler mit -Wall durchlaufen lassen?
ja #define BLUE 10 ist klar ;) vertippt wegene andere progsprache
-wall ist standart on
wie gesagt:
varibale lokal - alles funzt
varibale gloabl static - alles funzt
varibale global - nix funzt
danke
Das klingt nach verschiedenen Datensegmenten -- evtl. muß man den
Pointer konvertieren oder je nach Zielspeicherbereich speziell
definieren beim Atmel? Beim 8051 ist das so.
SO JETZT DREH ICH BALD DURCH:
versuch 1:
//GLOBAL DEFINIERT
tSquare square;
versuch 2: !!! FUNKTIONIERT !!!
//GLOBAL DEFINIERT
tSquare mySquare;
d.h. name der variable geändert von 'square' auf 'mySquare' dann
funktionierts auch glboal ohne static ???!?!?!?!?!?!?!?!?!?!?!!! (ist
square reserviertes word ?)
ja es ist spät
aber in der math.h definiert :
/**
\ingroup avr_math
The function square() returns <tt>x * x</tt>.
\note
This function does not belong to the C standard definition.
*/
extern double square(double __x) _ATTR_CONST_;
1.) gcc -O0 -save-temps gibt auch die Assembler-Datei aus (*.s).
Vielleicht der einfachste Weg um zu sehen, welches Symbol tatsächlich an
die Zeichenroutine übergeben wird.
2.) gcc -g -O0 -Wl,-M gibt die Linkmap aus. Darin nachsehen, was
wirklich für das Symbol square gelinkt wird (und außerdem, welche
Symbole in der Nähe liegen. Vielleicht wird square ja versehentlich
innerhalb einer ISR überschrieben? Oder durch ein sprintf)?
3.) Anbei ein Testprogramm, welches ohne UART auskommt, indem es die
Farbe des LCD ansteuert (ist natürlich anzupassen). Lokale Variablen
können gleichnamige Funktionsdeklarationen überdecken, und sollen das
auch können.
Denkbar wäre noch, daß der verwendete Compiler "square" als
intrinsische Funktion erkennt, und demnach die Adresse dieser Funktion
"square" übergibt, anstatt die Adresse der Variablen. Dann wäre es eben
doch ein Compiler-Fehler.
Übrigens würde ich erstmal nicht von einem Compiler-Bug aussehen. Man
bräuchte erstmal mehr Informationen zum Quelltext, bzw. eine minimale
Code-Version, bei der der Fehler auftritt. So ein Bug wäre mit
Sicherheit schon aufgefallen.
und im lss file ist das symbol 'square' definiert - und diese wird
verwendet - natürlich steht hier nur schrott drinnen ;)
000011f8 <square>:
11f8: 9b 01 ac 01 0c 94 00 09 ........
Ich kann mich Simon Küppers nur anschließen. Es ist Zeit für ein
Minimalprogramm, welches den Fehler reproduziert. Anhand der hier
gegebenen Daten kann man das nicht wirklich. Es ist klar, daß die
Funktion square verwendet wird, aber es ist durchaus nicht
nachvollziehbar, in welchem Zusammenhang.
hi
folgende 2 test-programme zeigen den unterschied (erstellt unter
avrstudio):
//=== 1 ========================
int test;
int main() {
test += 1;
return 0;
}
//=== 2 ========================
int square;
int main() {
square += 1;
return 0;
}
nach durchsicht des .lss und .map file wird der unterschied ersichtlich
;)
im anhang mein eigentliches projekt:
atmega128/siemens s65 display
tetris portiert von c# nach c
gruss
Warnung:
builtin function sqrt declared as non-function
Seit wann sind die Funktionen der Standardbibliothek reservierte
Wörter?
(Das EXE hat dann übrigens, 788 Bytes. Mit einem Variablennamen
'test' lediglich 178 Bytes)
Ich denke mal das ganze hängt damit zusammen, dass der Optimizer
über einige Funktionen Bescheid weiss und dieses Wissen zur
Optimierung benutzen kann.
Jörg: Sind das beim gcc nicht die intrinsischen (intrinsic)
Funktionen?
Wie ich den gcc kenen, gibt es da sicher einen Compilerswitch
mit dem man das abschalten kann. Nur finde den mal unter den
hunderten möglichen Switches.
Pragmatische Lösung: Nenne das Teil nicht 'square' sondern
'block' oder 'tile'.
Ganz interessant sind auch die Analysen des Formatstrings und der
Parameter, die neuere gcc (zumindest arm-elf) bei Xprintf schon zu
Compilezeit durchführen. Praktisch.
gert wrote:
>> lustig dass bei 'square' nicht mal ne warnung rauschgeschrieben wird>
liegt vermutlich daran, dass square(), im Gegensatz zu sqrt(),
keine 'offizielle' Standardfunktion ist.
Karl heinz Buchegger wrote:
> Seit wann sind die Funktionen der Standardbibliothek reservierte> Wörter?
7.1.3 Reserved identifiers
...
-- All identifiers with external linkage in any of the following
subclauses (including the future library directions) are always
reserved for use as identifiers with external linkage.157)
> Ich denke mal das ganze hängt damit zusammen, dass der Optimizer> über einige Funktionen Bescheid weiss und dieses Wissen zur> Optimierung benutzen kann.
Genau so ist es.
> Wie ich den gcc kenen, gibt es da sicher einen Compilerswitch> mit dem man das abschalten kann. Nur finde den mal unter den> hunderten möglichen Switches.
-ffreestanding :-)
Wir sollten unsere eigenen Erweiterungen unter Umständen so kapseln,
dass sie mit Schaltern wie -ansi nicht zur Verfügung stehen.
> Pragmatische Lösung: Nenne das Teil nicht 'square' sondern> 'block' oder 'tile'.
Ja, das würde ich auch sagen. "static" müsste auch helfen, wenn man
es auf file scope reduzieren kann. (Das ist ohnehin eine sinnvolle
Idee für alles, was man tut: den Scope immer auf das notwendige
Minimum einengen.)
Wobei mir gerade nicht klar ist: wenn <math.h> nicht included ist,
sollte eigentlich nichts passieren. Wenn es included ist, sollte der
Compiler sich darüber beschweren, dass die beiden Deklarationen/
Definitionen nicht zusammen passen.
Jörg Wunsch wrote:
> Wobei mir gerade nicht klar ist: wenn <math.h> nicht included ist,> sollte eigentlich nichts passieren.
Das war auch meine Hypothese. Die ist aber kläglich gescheitert.
Ich konnte es gar nicht glauben :-)
Karl heinz Buchegger wrote:
>> Wobei mir gerade nicht klar ist: wenn <math.h> nicht included ist,>> sollte eigentlich nichts passieren.>> Das war auch meine Hypothese. Die ist aber kläglich gescheitert.> Ich konnte es gar nicht glauben :-)
Ich kann es allerdings nicht reproduzieren. Wenn ich obigen simplen
Test (extra mit -O0, damit er die Variable nicht wegoptimiere)
compiliere, bekomme ich:
1
% avr-nm foo.elf
2
000000ba t .do_clear_bss_loop
3
000000bc t .do_clear_bss_start
4
...
5
00800100 A _edata
6
00800102 A _end
7
000000f4 T _etext
8
000000f2 T _exit
9
000000f2 W exit
10
000000ce T main
11
00800100 B square
also eindeutig eine Variable square im .bss. Ja, ich habe gegen -lm
gelinkt (aber davon wird natürlich nichts benötigt).
Ah ja... ich seh da was. Da wollte einer besonders gut sein und
war eher dilletantisch. Verschiedene trigonometrische Funktionen
in libm.a referenzieren square() direkt. Damit ist das Teil dann
natürlich drin und auch an jeglicher Typprüfung des Compilers vorbei.
Der Linker merkt das dann nicht mehr.
Bitte schreibt einen avr-libc-Bugreport.
Jörg Wunsch wrote:
> Karl heinz Buchegger wrote:>>>> Wobei mir gerade nicht klar ist: wenn <math.h> nicht included ist,>>> sollte eigentlich nichts passieren.>>>> Das war auch meine Hypothese. Die ist aber kläglich gescheitert.>> Ich konnte es gar nicht glauben :-)>> Ich kann es allerdings nicht reproduzieren. Wenn ich obigen simplen> Test (extra mit -O0, damit er die Variable nicht wegoptimiere)
Ich hatte -Os benutzt und nicht gegen -lm gelinkt.
Nachtrag: Hab jetzt nochmal mit -O0 compiliert. Gleicher Effekt.
Ich hab hier den WinAVR-20070525
Und du hast obiges ,,Minimalprogramm'' compiliert?
Kannst du mir die Compilerkommandozeile nennen und ggf. auch das
ELF-File hier als Attachment posten?
Jörg Wunsch wrote:
> Und du hast obiges ,,Minimalprogramm'' compiliert?
Ja.
Genau so wie es da steht.
Ohne irgendwelche Includes.
> Kannst du mir die Compilerkommandozeile nennen und ggf. auch das> ELF-File hier als Attachment posten?
Jetzt hast du mich erwischt :-)
Ich benutze die Standardeinstellung vom AVR-Studio.
Ich deh mal zu, dass ich an das Makefile rankomme, welches
AVR-Studio benutzt.
Also:
Der Compileraufruf
avr-gcc.exe -mmcu=atmega16 -Wall -gdwarf-2 -O0 -MD -MP -MT ForumTest.o
-MF dep/ForumTest.o.d -c ../ForumTest.c
Im Anhang das makefile und das ELF-File
Nein, für mich klappt es nicht, egal wie ich es drehe. Einziger
Unterschied hier: ich habe kein WinAVR, sondern benutze ,,nur''
das von Karl Heinz mitgegebene Makefile. In jedem Falle wird bei
mir sqrt oder square eine Variable auf Adresse 0x60. Es ist mir
auch nach wie vor komplett unlogisch, warum das anders sein soll --
schließlich wird -lm ja gar nicht angegeben, und sowohl square als
auch sqrt kommen ausschließlich in der libm.a vor, nicht in der
libc.a. Selbst wenn sie in der libc.a wären, würden deren Module
von diesem einfachen Programm nicht referenziert, also holt sie
der Linker auch nicht rein.
Wie gesagt, ich sehe den Bug (die trigonometrischen Funktionen haben
nicht das Recht, eine Implementierung einer Hilfsfunktion namens
square mit ins Boot zu ziehen, da dieser Name im application name
space liegt), habe aber keinen Schimmer, warum der bei euch zuschlägt.