Forum: Mikrocontroller und Digitale Elektronik merkwürdiger Aufruf vor Speicherzugriffen


von brechbunkt (Gast)


Lesenswert?

Hallo,

vor einem Schreibzugriff (SRAM) auf eine Struktur wird in Atmels ASF 
(z.B. bei den FIFOs) dieser Befehl aufgerufen:
1
    // Must be the last thing to do.
2
    barrier();

Wenn man sich diesen in der compiler.h anschaut, verbirgt sich das hier 
dahinter:
1
/**
2
 * \def barrier
3
 * \brief Memory barrier
4
 */
5
#if defined(__GNUC__)
6
#  define barrier()        asm volatile("" ::: "memory")
7
#elif defined(__ICCAVR32__)
8
#  define barrier()        __asm__ __volatile__ ("")
9
#endif

Hat jemand eine Ahnung was hiermit bewirkt werden soll?

von Random .. (thorstendb) Benutzerseite


Lesenswert?

so weit ich weiss sorgt eine barrier dafür, dass alle Zugriffe (z.B. 
Schreibzugriffe) nach der barrier abgeschlossen sind, vgl. z.B. __DMB(); 
__ISB(); beim Cortex-M3.
Dadurch sind die Daten beim drauffolgenden Zugriff garantiert 
konsistent.

: Bearbeitet durch User
von brechbunkt (Gast)


Lesenswert?

Aber wenn ich diese Speicheradresse als "volatile" deklariere, sollte 
doch diese Adresse dann ebenfalls ganz sicher beschrieben sein. Oder?

von Karl H. (kbuchegg)


Lesenswert?

Ich denke eher, dass es bei einer Barriere darum geht, den Compiler 
insofern einzuengen, dass er Speicherzugriffe nicht wahllos im Code 
rumschieben darf.

In
1
   i = 5;
2
   j = 8;

könnte der Compiler auch die Reihenfolge der Zuweisungen umdrehen, wenn 
ihm das besser in den Kram passt, weil er zb j (oder die Adresse von j) 
schon in einem CPU Register hatte.
1
...
2
   j = k;
3
   i = 5;
4
   j = 8;
5
...

Erwarten würde ich solche Dinge, wenn es in den STrukturen zb logische 
Querverbindungen gibt. Wenn also Werte von zb einem Gültigkeitsflag 
abhängen und es wichtig ist, dass die Wertzuweisung erfolgt, bevor das 
Flag auf gültig gesetzt wird. Dreht der Compiler aus irgendeinem Grund 
die Reihenfolge der Aktionen um, dann ergibt das einen logischen Fehler.

von Fred (Gast)


Lesenswert?

brechbunkt schrieb:
> Aber wenn ich diese Speicheradresse als "volatile" deklariere, sollte
> doch diese Adresse dann ebenfalls ganz sicher beschrieben sein. Oder?

Nein.

volatile garantiert dir keine Ausführungsreihenfolgen oder sonstiges 
zeitliches Verhalten.

volatile sagt nur, daß der Zugriff stattfinden muß. Wann (insbesondere 
vor welchen anderen Zugriffen), kannst du nicht damit steuern.

von Sven (Gast)


Lesenswert?

Der Barrier Befehl sorgt dafür, dass über diese Grenze KEINE 
Memory-Zugriffe verschoben werden. Sprich alles was vor Barrier codiert 
wurde, wird auch vorher ausgeführt, die Reihenfolge davor kann aber von 
der im Code hingeschriebenen abweichen, wenn der Compiler es für besser 
hält. Gerade, wenn er zusammenhänge nicht erkennen kann.

    value = 0815
    written = 1

kann dann zu

    written = 1
    value = 0815

werden. Der Compiler geht hier von unabhängigen Dingen aus. Was passiert 
aber bei sowas im 2. Thread:

    while ( written )
       ;
    read = value
    written = 0

Hier sind also entweder atomics oder barriers notwendig:

    value = 0815
    barrier()
    written = 1

Beim 2. Thread ist etwas ähnliches erforderlich.

Volatile sorgt lediglich dafür, dass ein Zugriff IMMER passiert. Auf 
Multiprozessorsystemen ist aber auch volatile mit Vorsicht zu genießen, 
da es sich nicht unbedingt um Cache-Kohärenz kümmern muss, es kann also 
auch ein schon veralteter Wert gelesen werden.

Dort ist z.B. ein atomic einem volatile vorzuziehen, da sich dieser auch 
um den Cache, etc. kümmert.

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
Noch kein Account? Hier anmelden.