Worum gehts den bei 'volatile'.
Volatile sagt dem Compiler, dass er keine Optimierungen
auf der Variablen machen soll.
Das ist wichtig in Fällen wie:
uint8_t flag
ISR( ... )
{
flag = 1;
int main()
{
...
flag = 0;
while( flag == 0 ) {
...
}
}
Ein optimierender Compiler kann (und wird) drauf kommen, dass
seiner Ansicht nach es in main() keine Möglichkeit gibt, dass
flag jemals etwas anderes als 0 sein kann. Daher kann er zu
dem Schluss kommen, das es keine Möglichkeit gibt die Schleife
jemals zu verlassen und er daher die Abfrage ob flag immer
noch 0 ist rauswerfen kann. Seiner Ansicht nach ändert sich
dadurch nichts an der Programmlogik.
Das es einen 2-ten, asynchronen Pfad gibt, in dem flag zu 1
werden kann, kriegt er einfach nicht mit.
Ein anderes Scenario wäre, wenn der Compiler beschliesst, dass
er flag in ein Register lädt und dort auch belässt. Dadurch
muss bei der Abfrage von flag dessen Wert nicht jedesmal aus
dem Speicher geholt werden, sondern liegt schon in einem Register
vor.
Mit volatile kann das behoben werden: volatile verbietet jegliche
Optimierung auf einer Variablen, sodass:
* der Compiler die Schleifenbedingung da oben auf jeden Fall
immer neu auswerten muss
* die Variable nicht in einem Register zwischengespeichert
werden darf.
Nur: Speziell für die Zwischenspeicherung in einem Register
muss der Datentyp natürlich auch dafür geeignet sein. Ein
Array ist das aber ganz sicher nicht, sodass keine Gefahr
besteht, dass gcc hier eine Registeroptimierung vornehmen
wird.
Hmm. Das hindert aber die Datenflussanalyse nicht festzustellen,
dass isch das Array nicht im Schleifendurchlauf ändert. ....
Ich zieh meine Aussage zurück. Mach das Array volatile.