AUf Kriegsfuß mit dem AVR-GCC.

Gast #1269056
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
Angehängte Dateien:
Persönliche Seite #1269074
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 ;-)
1
#include <avr/io.h>
2

3
uint8_t status = 0x01;
4

5
int main(void)
6
{
7
    while(1)
8
    {
9
        if(status & 0x01)
10
        {
11
            status &= ~0x01;
12
        }
13

14
        if(status & 0x02)
15
        {
16
            status &= ~0x02;
17
        }
18
    }
19

20
    return 0;
21
}

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

HTH,
Falk
Persönliche Seite #1269857
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.
Persönliche Seite #1269887
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
Gast #1269892
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...
Persönliche Seite #1269955
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.
#1270006
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.)
Moderator Persönliche Seite #1270597
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.
Persönliche Seite #1270693
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:
1
extern const volatile char x;
2

3
void foo ()
4
{
5
    while (x);
6
}

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

Johann
#1270748
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.
#1270750
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.
Gast #1270830
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.
#1271501
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:
>
>
1
> extern const volatile char x;
2
> 
3
> void foo ()
4
> {
5
>     while (x);
6
> }
7
>
>
> Wird mit avr-gcc 4.3.2 (dito blah-gcc) mit -Os zu
>
1
> foo:
2
>   lds r24,x   ;  x.0, x
3
> .L2:
4
>   tst r24   ;  x.0
5
>   brne .L2
6
>   ret
7
>
>
> 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
Moderator Persönliche Seite #1271522
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.
#1271523
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren