mikrocontroller.net

Forum: Compiler & IDEs Warnung bei volatile (AVR-GCC)


Autor: Günter R. (galileo14)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

kann mir jemand auf die Sprünge helfen? Habe im Forum nach "volatile"
gesucht, aber über die folgende Warnung hat noch niemand berichtet
(vielleicht ist der Grund auch trivial??).

In einer RTC-Funktion wird ein Zeit/Datum-Array "TimeDate" erhöht;
die RTC-Funktion wird von einem Timer-Interrupt aufgerufen (im
Minutentakt, entsprechend heruntergeteilt). Früher hatte ich das
"volatile" bei "TimeDate"-Deklaration vergessen, da war noch alles
okay, hat auch  funktioniert (vielleicht auch nur "zufällig" - okay,
bei Computern gibt es keine Zufälle).

Dann erkannte ich das Versäumnis, daß Variablen, die in
Interrupt-Funktionen verändert werden, als volatile deklariert werden
müssen. Habe dann das "volatile" hinuzgefügt; das Programm
funktioniert natürlich immer noch, aber nun erscheinen Warnungen bei
den "memcpy"-Funktionen (gibt noch mehr, als im Code-Fragment
steht):

../main.c:1936: warning: passing arg 2 of `memcpy' discards qualifiers
from pointer target type


Code-Fragment:

#define TIMEDATENUMBYTES 5   /* Zahl der Bytes der TimeDate-Arrays */

volatile uint8_t TimeDate[TIMEDATENUMBYTES]; /* hh:mm dd:mm:yy */

...


void ZeitDatumAnzeigen(void)
{
  uint8_t timedate[TIMEDATENUMBYTES]; /* lokale TimeDate-Variable */

  ...

  sreg=SREG;     /* Globale Zeit lokal kopieren */
  cli();
  memcpy(timedate,TimeDate,sizeof(timedate));
  SREG=sreg;

  fprintf_P(&DevLCD,PSTR("%02u:%02u   %02u.%02u.%02u"),
     timedate[0],timedate[1],timedate[2],timedate[3],timedate[4]);

  ...
}


Wahrscheinlich erscheinen die Warnungen im Zusammenhang mit der
Verwendung von Zeigern ("TimeDate" ist ja ein Zeiger) und der
Deklaration von "memcpy", das ja nicht mit "volatile" deklariert
ist.

Die Warnung stört mich, obwohl alles funktioniert. Weiß jemand, wie man
sie wegbekommen kann?

Danke.

Günter

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit einem Typecast:

  memcpy(timedate, (void *) TimeDate, sizeof (timedate));

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du bist da in einer Zwickmühle.

Die Warnung besagt logisch gedacht, dass das volatile von memcpy()
nicht beachtet wird. Und das ist eine gute Warnung.

memcpy() nimmt beim Kopieren keine Rücksicht darauf, dass sich der
Inhalt der Quelle während der Kopieraktion ändern kann. memcpy setzt
sogar voraus, dass sich die Quelle nicht ändert (Deklaration mit const
void *).

Du berücksichtigst das Verhalten von memcpy() bereits, indem du mit
cli() die Interrupts sperrst, so dass sich der Inhalt von TimeDate
nicht mehr ändern kann.

Um die Warnung an dieser Stelle wegzubekommen, finde ich es legitim
einen cast einzufügen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn man allerdings die Warnung erfolgreich mit dem Cast los wird
und der Code danach trotzdem noch funktioniert, ist das eigentlich
das beste Zeichen, dass es in diesem Falle des "volatile"s gar
nicht bedurft hätte.

> memcpy setzt sogar voraus, dass sich die Quelle nicht ändert
> (Deklaration mit const void *).

Nein, diese Deklaration besagt, dass es selbst das Objekt, auf das
der Zeiger zeigt, nicht ändern möchte.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Dann erkannte ich das Versäumnis, daß Variablen, die in
> Interrupt-Funktionen verändert werden, als volatile deklariert werden
> müssen.

Und auch das stimmt so nicht.
Von müssen kann keine Rede sein.

Das volatile ist im Grunde nur für den wichtig, der diese Variable auch
benutzt. Wie zb hier:

   while( j == 5 )
     ;

ist j nicht volatile deklariert, so geht der Compiler davon aus, dass
j sich in der Schleife nicht ändern kann und optimiert entsprechend.
Eine volatile Deklaration hingegen sagt dem Compiler: "Du weist auch
nicht alles über diese Variable. Die Variable kann sich ändern, ohne 
dass
es in dem Code-Stück, das du überblicken kannst, ersichtlich wäre."

Das macht volatile und das hat erstmal nichts mit Interrupts an sich
zu tun.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg: "Wenn man allerdings die Warnung erfolgreich mit dem Cast los 
wird
und der Code danach trotzdem noch funktioniert, ist das eigentlich
das beste Zeichen, dass es in diesem Falle des "volatile"s gar
nicht bedurft hätte."

Dieser Logik folgend wird man, wenn man mit eher einfach gestrickten 
Compilern arbeitet, nie volatile benötigen. Und sich fuchsteufelswild 
über einen völlig unbrauchbaren GCC ärgern, der das halt etwas anders 
sieht.

Nein, so läuft das nicht. Array-Zugriffe werden in der Praxis oft kein 
volatile benötigen. Aber irgendwann vielleicht schon. Also muss es sein, 
auch dann wenn sich erst einmal nichts ändert.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Array-Zugriffe werden in der Praxis oft kein
> volatile benötigen. Aber irgendwann vielleicht schon.

Nein, brauchen sie nicht.  Das ist nur die Kurzfassung, für die
Formulierung der Langfassung, warum sie (*) kein "volatile" brauchen,
würde ich vermutlich eine halbe Stunde benötigen, um die
entsprechenden Stellen des Standards herauszusuchen und zu zitieren.

Wenn man das Beschreiben eines Arrays zwischen zwei Threads (also
z. B. zwischen Interrupt- und Hauptkontext) synchronisieren will,
sollte man das über eine (dann wirklich "volatile" qualifizierte)
Semaphore-Variable machen.

Du kannst dir ziemlich sicher sein, dass der GCC an dieser Stelle
bereits alles ausnutzt, was der Standard gestattet.

(*) In der Regel -- du kannst natürlich pathologische Fälle
provozieren, wenn du sowas hast wie
uint8_t myarr[42];

...

   while (myarr[23] != 5)
     /* wait until it's 5 */ ;

Autor: Günter R. (galileo14)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke an alle - Problem ist gelöst mit dem "(void *)" (hätte ich selber 
drauf kommen können, aber manchmal hat man ja Tomaten auf den Augen).

Danke auch für den Hinweis von Jörg - ja, man kann hier "volatile" 
bestimmt weglassen; aber der Klarheit wegen lasse ich's doch drin (es 
wird nicht schaden).

Günter

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> (es wird nicht schaden).

Es ,,pessimiert'' den Code.

Autor: Günter R. (galileo14)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was meinst Du denn damit? Pessimistischer Code? Davon habe ich noch nie 
gehört ...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
,,pessimieren'' ist einfach das Gegenteil von ,,optimieren''. ;-)

Autor: Günter R. (galileo14)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach so, Wortspiel. Okay. Ich überleg's mir nochmal, ob ich das volatile 
entferne.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.