mikrocontroller.net

Forum: Compiler & IDEs AVR: Konstante 0 ist nicht 0 in ISR


Autor: Jantronics (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
ucBufferState = EEPROM_BUFFER_READY;

Dabei ist ucBufferState eine globale Variable vom Typ volatile unsigned 
char und EEPROM_BUFFER_READY ein Makro:
#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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Such mal dein Programm nach Arrayüberläufen ab.
Meistens ist es irgendsowas, wenn Variablen anscheinend
ohne Grund ihren Wert ändern.

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist "ucBufferState" auch als "volatile" Variable definiert?

Autor: Jantronics (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Jantronics (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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'.

Autor: Jantronics (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.