> Ich deklariere die variable mit volatile in einem File data.c und
> mit extern in einem file data.h, das ich dann include.
Lass mich raten: bei "extern" hast du kein "volatile" davor, ja?
> Was mache ich falsch?
Genau das. Überleg' doch mal, wie ein Compiler arbeitet.
"volatile"
ist ein sogenannter type qualifier, er bestimmt also einen bestimmten
Typ näher. In diesem Falle werden durch diese Bestimmung bestimmte
Zugriffe auf diese Variable nicht mehr optimiert. Nun spiel' mal
Compiler:
data.h:
data.c:
1 | #include "data.h"
|
2 |
|
3 | volatile uint8_t x;
|
main.c:
1 | #include "data.h"
|
2 |
|
3 | int
|
4 | main(void)
|
5 | {
|
6 | /* ... */
|
7 | while (x == 0) {
|
8 | }
|
9 | /* ... */
|
10 | return 42;
|
11 | }
|
Was sieht der Compiler nach dem Präprozessor?
data.i:
1 | extern uint8_t x;
|
2 |
|
3 | volatile uint8_t x;
|
Das erste ist eine Deklaration, das zweite eine Definition.
Eigentlich solltest du eine Compilerwarnung bekommen, da die
qualifiers zwischen beiden verschieden sind.
main.i:
1 | extern uint8_t x;
|
2 |
|
3 | int
|
4 | main(void)
|
5 | {
|
6 | /* ... */
|
7 | while (x == 0) {
|
8 | }
|
9 | /* ... */
|
10 | return 42;
|
11 | }
|
main.i ist nun aber die Stelle, an der der Compiler tatsächlich auf x
zugreift und wissen muss, dass sie `volatile' ist. Nur: er weiß es
nicht. Woher auch? Das Einzige, was er an dieser Stelle weiß ist,
dass sie vom Type uint8_t ist und dass es sie ,,irgendwo'' (wo
genau,
weiß erst der Linker) außerhalb des aktuellen Übersetzungsmoduls
(compilation unit) gibt. Da er nicht weiß, dass sie eigentlich
volatile ist, wird er deren Wert aber am Beginn der while-Schleife
genau einmal einlesen und danach nie wieder.