Hallo, ich habe folgendes Problem: Ich verwende einen ATmega 32 und habe
eine ISR für den EEPROM ready interrupt geschrieben. Darin gibt es eine
Zuweisung:
1
ucBufferState=EEPROM_BUFFER_READY;
Dabei ist ucBufferState eine globale Variable vom Typ volatile unsigned
char und EEPROM_BUFFER_READY ein Makro:
1
#define EEPROM_BUFFER_READY 0
Es soll also ucBufferState schlicht der konstante Wert 0 zugewiesen
werden. Dies gelingt aber nicht, ucBufferState bekommt irgendeinen
anderen Wert. Dieses Problem tritt nur beim Wert 0 auf, verwende ich z.
B. als Konstante eine 1 funktioniert das Ganze wie gewünscht. Das taugt
zwar durchaus als work around, dennoch würde ich das Problem gerne
verstehen, denn sonst könnte ich mich nicht mehr auf Vergleiche oder
Zuweisungen mit einer konstanten 0 verlassen.
Auch ne Möglichkeit:
Hast du irgendwo ASM-Code dazugelinkt (oder inline-ASM), der das
GCC-Zero-Register überschreibt, üblicherweise "r1" ?
das muss auf jeden Fall wieder auf 0 zurückgesetzt werden, und
interrupts sperren während r1 != 0... Am besten garnicht erst anfassen.
Beim r1 Register liegt der Hund wohl tatsächlich begraben, ein Blick in
das Assemblerlisting zeigt seine ursächliche Beteiligung an dem
Shringsel. Es scheint tatsächlich != 0 zu sein. Nur mache ich das
nirgendwo wissentlich. Da muss ich nochmal genauer nachforschen. Danke
schon mal für den Hinweis!
Nachtrag: Es hat sich herausgestellt, dass mein Problem ein gänzlich
anderes wahr. Der Annahme, dass das r1-Register in der ISR nicht den
Wert 0 hat, widersprach die GCC-Doku, die besagt, dass r1 beim ISR
Aufruf gerettet und anschließend zwangsweise auf 0 gesetzt wird. Ein
weiterer Blick in das Listing bestätigte dies auch.
Der Fehler bestand vielmehr darin, dass es dem Compiler gefiel, zwei
globale Variablen, die sich in unterschiedlichen Modulen befanden,
jedoch den gleichen Namen trugen, als ein und dasselbe anzusehen,
selbstverständlich ohne Warnung geschweige denn einer Fehlermeldung.
Nunja, unterschiedlich genannt - und alles wird gut...
Jantronics wrote:
> Der Fehler bestand vielmehr darin, dass es dem Compiler gefiel, zwei> globale Variablen, die sich in unterschiedlichen Modulen befanden,> jedoch den gleichen Namen trugen, als ein und dasselbe anzusehen,> selbstverständlich ohne Warnung geschweige denn einer Fehlermeldung.
Dafür sind es doch globale Variablen. Die sind per definitionem
identisch. Warum sollte es dafür eine Warnung geben? Der Linker
würde dich warnen, wenn beide Module versuchen, das gleiche Symbol
mit einer unterschiedlichen Größe zu benutzen, aber in allen anderen
Fällen geht er davon aus, dass das so gewollt war. Das ist im
C-Standard ausdrücklich zulässig (und im C99 Rationale als eine der
möglichen Belegungstrategien für Variablen erklärt).
Wenn du das abschalten willst (dann schaltest du auf eine andere
Belegungsstrategie um, die ebenfalls im Rationale als eine Möglichkeit
erläutert ist), dann geht das mit der Compileroption -fno-common.
Ansonsten ist es halt einfach guter und sinnvoller Programmierstil,
nur solche Objekte und Funktionen global zu deklarieren, für die das
notwendig ist. (Deren Deklaration sollte dann auch in ein von allen
Modulen gemeinsam genutztes Headerfile gehen.) Alles andere wird
`static', dann passieren derartige Unfälle auch nicht. Es ist ein
Versäumnis, dass `static' nicht der Default ist, sondern `global'.
Danke für die Info mit der Compiler-Option. Ich war es allerdings bisher
gewohnt, dass ich eine über mehrere Module globale Variable in einem
Modul definiere und in den anderen als "extern" deklariere, oder, wie
schon gesagt, in einem gemeinsamen Header definiere. Naja, was soll's,
der eine Compiler macht's so, der andere anders, muss man halt wissen.
Jantronics wrote:
> Ich war es allerdings bisher> gewohnt, dass ich eine über mehrere Module globale Variable in einem> Modul definiere und in den anderen als "extern" deklariere, ...
Ist ja auch der vernünftige Weg.
Ich vermute, GCCs Verhalten (das dem des klassischen Unix-C-Compilers
entsprechen dürfte) rührt einfach aus einer Zeit her, da C das
Schlüsselwort "extern" noch nicht kannte. Damit konnte nicht zwischen
Definition und Deklaration einer globalen Variablen unterschieden
werden. Später hat man das möglicherweise aus Kompatibilitätsgründen
im Compiler beibehalten, damit sich der bereits existierende Code
noch genau so verhält wie früher.
Wie geschrieben, das ist aber reine Spekulation. Man sollten in
Erinnerung behalten, dass in den 1970er Jahren einfach manche Dinge
bezüglich Programmierstil anders gesehen worden sind.