mikrocontroller.net

Forum: Compiler & IDEs AUf Kriegsfuß mit dem AVR-GCC.


Autor: robbse (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich denke dass mein Problem für Euch bestimmt kein großes Hindernis 
darstellt, aber ich blicks halt nicht! Ich habe bei uns in der Firma ein 
paar mal mit dem IAR-Compiler was geschrieben und wollte nun meinen Code 
mit GCC ähnlich strukturieren. Habe im Hauptprogramm nur Abfragen auf 
Statusbits laufen, die in Interrupts gesetzt werden (funktioniert). 
Dummerweise scheint diese simple (?) Statusbitabfrage nicht zu gehen! 
Habe mal ein AVR Studio Projekt angehangen, welches sich schon im 
Simulator aufhängt. Wenn Ihr also so freundlich wärt mir diese Eigenheit 
zu erklären..? Danke!

robbse

Autor: Falk Willberg (dl3daz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
robbse schrieb:
> Hallo zusammen,
...
> Habe im Hauptprogramm nur Abfragen auf
> Statusbits laufen, die in Interrupts gesetzt werden (funktioniert).
> Dummerweise scheint diese simple (?) Statusbitabfrage nicht zu gehen!
> Habe mal ein AVR Studio Projekt angehangen, welches sich schon im
> Simulator aufhängt. Wenn Ihr also so freundlich wärt mir diese Eigenheit
> zu erklären..? Danke!

Ich habe mir mal erlaubt, den vollständigen C-code aus dem 7kB .zip zu 
extrahieren ;-)
#include <avr/io.h>

uint8_t status = 0x01;

int main(void)
{
    while(1)
    {
        if(status & 0x01)
        {
            status &= ~0x01;
        }

        if(status & 0x02)
        {
            status &= ~0x02;
        }
    }

    return 0;
}

Wenn die Variable "status" in einer ISR geändert wird, muß sie als 
"volatile" deklariert werden.

HTH,
Falk

Autor: Matthias H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fehlt da nicht noch ein #include <stdint.h>?

Autor: robbse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt! Danke :oD

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aus Sicht des C Compilers ist dieser Code vergleichbar mit
int main(void)
{
    while(1)
    {
    }
}

weil die Variable keine sichtbare Auswirkung hat.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias H. schrieb:
> fehlt da nicht noch ein #include <stdint.h>?

inttypes.h kommt mit avr/io.h, wenn __ASSEMBLER__ nicht define'd ist.

Johann

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

Bewertung
0 lesenswert
nicht lesenswert
Falk Willberg schrieb:

> Wenn die Variable "status" in einer ISR geändert wird, muß sie als
> "volatile" deklariert werden.

Ist aber beim IAR auch nicht anders, wenn man nicht gerade die
Optimierungen abschaltet...

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falk Willberg schrieb:

> Wenn die Variable "status" in einer ISR geändert wird, muß sie als
> "volatile" deklariert werden.

Richtig. Und wenn Dein IAR-Compiler es trotzdem "richtig" macht, 
optimiert er halt schlecht. Da C allerdings standardisiert ist wirst Du 
Dich nicht darauf verlassen koennen, dass andere Versionen des Compilers 
es nicht doch optimieren und es dann ebenfalls nicht mehr funktioniert. 
Mit dem GCC hat das erst einmal garnichts zu tun.

Autor: Falk Willberg (dl3daz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael G. schrieb:
> Falk Willberg schrieb:
>
>> Wenn die Variable "status" in einer ISR geändert wird, muß sie als
>> "volatile" deklariert werden.
>
> Richtig. Und wenn Dein IAR-Compiler es trotzdem "richtig" macht,
> optimiert er halt schlecht.

Ich habe doch gar keinen IAR ;-)

> Da C allerdings standardisiert ist wirst Du
> Dich nicht darauf verlassen koennen, dass andere Versionen des Compilers
> es nicht doch optimieren und es dann ebenfalls nicht mehr funktioniert.

ISRs sind m.W. sowieso nicht Bestandteil irgendeines C-Standards.
Sobald der Compiler also das kleinste bischen optimiert, wird er 
feststellen, daß "status" höchstens mal in einer Funktion geändert wird, 
die nie aufgerufen wird.

> Mit dem GCC hat das erst einmal garnichts zu tun.

So isses, schrub ich aber auch nicht.

Falk

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. schrieb:
> Matthias H. schrieb:
>> fehlt da nicht noch ein #include <stdint.h>?
>
> inttypes.h kommt mit avr/io.h, wenn __ASSEMBLER__ nicht define'd ist.
>
> Johann

Nur der Vollständigkeit halber: inttypes.h ist nicht gleich stdint.h und 
auch nicht als Ersatz gedacht.

Wobei man sich nun natürlich fragen könnte, wozu im C-Standard ein 
'volatile' verankert ist, wenn es doch eigentlich 'offiziell' überhaupt 
keine Nebenläufigkeit (Threads, Interrupts) gibt...

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falk Willberg schrieb:

> ISRs sind m.W. sowieso nicht Bestandteil irgendeines C-Standards.
> Sobald der Compiler also das kleinste bischen optimiert, wird er
> feststellen, daß "status" höchstens mal in einer Funktion geändert wird,
> die nie aufgerufen wird.
>
>> Mit dem GCC hat das erst einmal garnichts zu tun.
>
> So isses, schrub ich aber auch nicht.

Der Kommentar bezog sich eigentlich auf den OP, Deinen Beitrag wollte 
ich nur untermauern ;)

Das hatte nur so den Anschein, dass er halt glaubt, GCC wuerde hier 
etwas falsch machen, aber im Endeffekt war sein urspruengliches Programm 
falsch, das sein Compiler aufgrund schlechter Optimierung zufaellig 
richtig uebersetzt hat.

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

Bewertung
0 lesenswert
nicht lesenswert
Sven P. schrieb:

> Wobei man sich nun natürlich fragen könnte, wozu im C-Standard ein
> 'volatile' verankert ist, wenn es doch eigentlich 'offiziell' überhaupt
> keine Nebenläufigkeit (Threads, Interrupts) gibt...

:-)
Weil es dann immer noch die Möglichkeit gibt, sich einen Pointer auf 
eine memory mapped unit zu generieren und sich Speicherzellen wie von 
Geisterhand selbst verändern.

Auf der anderen Seite: Wie kriegt man so einen Pointer als ordinäres 
C-Programm? Man kann eine Betriebssystemfunktion darum bitten. Meinem 
Verständnis nach ist man damit sowieso um undefined-land, wenn man 
diesen Pointer dereferenziert.
Oder man castet einen int zurecht. Aber auch das ist dann ein 
undefined-land Stunt.

(Oder wars unspecified. Kann mir nie merken, was von beiden was ist. 
Unspecified ist IMHO: Alles kann passieren. Und wenn die Welt dabei 
spontan untergeht, ist das auch ok.
Undefined: Die Welt darf zwar untergehen, allerdings nur dann wenns im 
Handbuch steht. Aber dann muss sie auch jedesmal untergehen.)

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

Bewertung
0 lesenswert
nicht lesenswert
Sven P. schrieb:

> Nur der Vollständigkeit halber: inttypes.h ist nicht gleich stdint.h und
> auch nicht als Ersatz gedacht.

Die Typdefinitionen von <stdint.h> sind eine Untermenge der
Definitionen von <inttypes.h>.  Ursprünglich hatte man wohl nur
<inttypes.h> definiert, das sowohl die Typnamen als auch allerlei
printf- und scanf-Format-Definitionen für deren Ein-/Ausgabe umfasst.
Dann hat man sich drauf besonnen, dass gerade embedded systems ggf.
zwar die Typnamen auch benutzen wollen, aber an den Konvertierungen
gar nicht interessiert sind.  Da hat man <stdint.h> als Untermenge
festgelegt.

> Wobei man sich nun natürlich fragen könnte, wozu im C-Standard ein
> 'volatile' verankert ist, wenn es doch eigentlich 'offiziell' überhaupt
> keine Nebenläufigkeit (Threads, Interrupts) gibt...

Die kann es in einer Implementierung schon geben, nur deren Details
sind nicht im Standard geregelt.  Das einzige Detail, was halt geregelt
ist, ist dabei volatile.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch schrieb:

> Die kann es in einer Implementierung schon geben, nur deren Details
> sind nicht im Standard geregelt.  Das einzige Detail, was halt geregelt
> ist, ist dabei volatile.

Wobei der aktuelle GCC da schwächelt und volatile nicht immer 
berücksichtigt. Hier nur ein einfaches Beispiel:
extern const volatile char x;

void foo ()
{
    while (x);
}

Wird mit avr-gcc 4.3.2 (dito blah-gcc) mit -Os zu
foo:
  lds r24,x   ;  x.0, x
.L2:
  tst r24   ;  x.0
  brne .L2
  ret

Johann

Autor: A. N. (netbandit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Johann:
Vielleicht erkennt GCC, dass es so wenig globale/lokale Variablen gibt, 
dass man x dort dauerhaft auf r24 legen könnte.

Vielleicht ändert sich das wenn das Programm größer wird und der GCC 
nicht mehr gewährleisten kann, dass r24 nicht woanders benutzt wird.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. N. schrieb:
> Vielleicht erkennt GCC, dass es so wenig globale/lokale Variablen gibt,
> dass man x dort dauerhaft auf r24 legen könnte.
>
> Vielleicht ändert sich das wenn das Programm größer wird und der GCC
> nicht mehr gewährleisten kann, dass r24 nicht woanders benutzt wird.

Mir ist nicht ganz klar, was du damit sagen willst.
x ist volatile deklariert, daher müsste er x in der Schleife immer 
wieder neu aus dem Speicher lesen, ganz unabhängig von irgendwelchen 
Optimierungen.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falls x überhaupt im Speicher angelegt wird. Wenn es eh direkt in ein 
Register gepackt wird fällt dieses aus dem Speicher holen weg.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast schrieb:
> Falls x überhaupt im Speicher angelegt wird. Wenn es eh direkt in ein
> Register gepackt wird fällt dieses aus dem Speicher holen weg.

x ist eine externe globale Variable.

Außerdem sieht man doch am lds vor der Schleife, dass x im Speicher 
existiert.

Autor: A. N. (netbandit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt, das war wohl schon etwas spät gestern Abend. Naja wäre nicht das 
erste mal, das gcc einen Fehler macht.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aus dem C99-Standard:

> The header <inttypes.h> includes the header <stdint.h> and extends
> it with additional facilities provided by hosted implementations.

Ich hab nix gesagt :-) War mir so garnicht bewusst.

Autor: Marcus Müller (marcus67)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. schrieb:
> Jörg Wunsch schrieb:
>
>> Die kann es in einer Implementierung schon geben, nur deren Details
>> sind nicht im Standard geregelt.  Das einzige Detail, was halt geregelt
>> ist, ist dabei volatile.
>
> Wobei der aktuelle GCC da schwächelt und volatile nicht immer
> berücksichtigt. Hier nur ein einfaches Beispiel:
>
>
> extern const volatile char x;
> 
> void foo ()
> {
>     while (x);
> }
> 
>
> Wird mit avr-gcc 4.3.2 (dito blah-gcc) mit -Os zu
>
> foo:
>   lds r24,x   ;  x.0, x
> .L2:
>   tst r24   ;  x.0
>   brne .L2
>   ret
> 
>
> Johann

extern const volatile char x;

Na ja, vielleicht hat das ja mit dem "const" in der Deklaration zu tun 
...
Warum sollte ein const sich ändern ...

Gruß, Marcus

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

Bewertung
0 lesenswert
nicht lesenswert
Marcus Müller schrieb:

> extern const volatile char x;
>
> Na ja, vielleicht hat das ja mit dem "const" in der Deklaration zu tun
> ...
> Warum sollte ein const sich ändern ...

Es könnte sich durch Hardware-Einflüsse ändern.  Diese Möglichkeit
wird vom Standard explizit eingeräumt:

EXAMPLE 1      An object declared
        extern const volatile int real_time_clock;
may be modifiable by hardware, but cannot be assigned to, incremented, 
or decremented.

Der Compiler muss also im Zweifelsfalle das const ignorieren, darf
das volatile aber nicht ignorieren.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcus Müller schrieb:

> Na ja, vielleicht hat das ja mit dem "const" in der Deklaration zu tun
> ...
> Warum sollte ein const sich ändern ...

In C gilt: const != konstant
Es sagt dem Compiler nur, dass er selber die Variable nicht ändern darf, 
nicht, dass sich der Wert gar nicht ändert. "const volatile" ist z.B. 
eine gute Beschreibung für ein Read-Only-Hardwareregister.

Autor: Marcus Müller (marcus67)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe ich in der Zwischenzeit auch nachgelesen - volatile "überstimmt" 
das const ...

Gruß, Marcus

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.