Hallo, ich habe ein char-Array als volatile deklariert, da ich sowohl in der ISR als auch in der main darauf zugreife (ein Zeichenpuffer für den UART-Eingang). Nun gibt mir der Compiler immer dann eine Warnung, wenn ich mit dem Array arbeiten möchte, z.B.: warning: passing arg 1 of `strncat' discards qualifiers from pointer target type Wahrscheinlich, weil er Zeiger auf char erwartet, aber volatile Zeiger auf char bekommt. Kann ich das einfach übergehen?
TechInfo wrote: > Hallo, > > ich habe ein char-Array als volatile deklariert, da ich sowohl in der > ISR als auch in der main darauf zugreife (ein Zeichenpuffer für den > UART-Eingang). > > Nun gibt mir der Compiler immer dann eine Warnung, wenn ich mit dem > Array arbeiten möchte, z.B.: > > warning: passing arg 1 of `strncat' discards qualifiers from pointer > target type > > Wahrscheinlich, weil er Zeiger auf char erwartet, aber volatile Zeiger > auf char bekommt. > > Kann ich das einfach übergehen? Ja kannst du. Du kannst in diesem Fall aber auch einfach das volatile vom Array wegnehmen. Die Fälle um die es bei volatile geht, sind mit Arrays beim gcc nicht realisierbar, sodass es kein Problem ist, Arrays nicht volatile zu machen.
Danke. Könntest du das noch weiter ausführen? Optimiert der Compiler Arrays nicht?
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.
Das Array volatile machen, hilft ja auch nicht, da er es eben an Funktionen übergeben will, für die es sowieso nicht volatile wäre. Da es trotzdem noch funktioniert, kann man sich das dann auch gleich klemmen. Solange man das Array nur im Ganzen nimmt, ist das OK. Was man natürlich nicht machen kann ist:
1 | uint8_t somearray[32]; |
2 | |
3 | ISR(FOO_vect) |
4 | {
|
5 | somearray[0] = 1; |
6 | ...
|
7 | }
|
8 | |
9 | int
|
10 | main(void) |
11 | {
|
12 | for (;;) { |
13 | while (somearray[0] != 1) |
14 | /* warten */ ; |
15 | somearray[0] = 0; |
16 | ...
|
17 | }
|
18 | }
|
Was aber geht ist:
1 | volatile uint8_t flag; |
2 | uint8_t somearray[32]; |
3 | |
4 | ISR(FOO_vect) |
5 | {
|
6 | somearray[...] = ...; |
7 | flag = 1; |
8 | }
|
9 | |
10 | int
|
11 | main(void) |
12 | {
|
13 | for (;;) { |
14 | while (flag != 1) |
15 | /* warten */ ; |
16 | flag = 0; |
17 | tuwas(somearray); |
18 | ...
|
19 | }
|
20 | }
|
In diesem Falle sorgt die volatile-Variable flag für die Synchronisation, der Compiler hat keinen Grund, somearray[] innerhalb von main() überhaupt zu bewerten. Das tut er erst innerhalb von tuwas(), und an dieser Stelle ist die ISR verlassen und damit auch der Inhalt des Arrays wieder stabil.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.