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
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_tstatus=0x01;
4
5
intmain(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
return0;
21
}
Wenn die Variable "status" in einer ISR geändert wird, muß sie als
"volatile" deklariert werden.
HTH,
Falk
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...
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.
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
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...
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.
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.)
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.
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:
@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.
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 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.
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.
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
>externconstvolatilecharx;
2
>
3
>voidfoo()
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
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.
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.