Frage Data Memory Barrier (DMB) in CMSIS-Bibliotheken für Cortex-M3s


In den CMSIS-Definitionen für gcc finden Sie so etwas:

static __INLINE void __DMB(void) { __ASM volatile ("dmb"); }

Meine Frage ist: Welchen Nutzen hat eine Speicherbarriere, wenn sie in der Clobberliste nicht "Speicher" deklariert?

Ist es ein Fehler in der Datei core_cm3.h oder gibt es einen Grund, warum gcc sich ohne zusätzliche Hilfe korrekt verhalten sollte?


5
2017-07-19 17:45


Ursprung


Antworten:


Ich habe ein paar Tests mit gcc 4.5.2 (mit LTO) gemacht. Wenn ich diesen Code kompiliere:

static inline void __DMB(void) { asm volatile ("dmb"); }
static inline void __DMB2(void) { asm volatile ("dmb" ::: "memory"); }

char x;

char test1 (void)
{
  x = 15;
  return x;
}

char test2 (void)
{
  x = 15;
  __DMB();
  return x;
}

char test3 (void)
{
  x = 15;
  __DMB2();
  return x;
}

verwenden arm-none-eabi-gcc -Os -mcpu=cortex-m3 -mthumb -c dmb.cdann von arm-none-eabi-objdump -d dmb.o Ich verstehe das:

00000000 <test1>:
   0:   4b01        ldr r3, [pc, #4]    ; (8 <test1+0x8>)
   2:   200f        movs    r0, #15
   4:   7018        strb    r0, [r3, #0]
   6:   4770        bx  lr
   8:   00000000    .word   0x00000000

0000000c <test2>:
   c:   4b02        ldr r3, [pc, #8]    ; (18 <test2+0xc>)
   e:   200f        movs    r0, #15
  10:   7018        strb    r0, [r3, #0]
  12:   f3bf 8f5f   dmb sy
  16:   4770        bx  lr
  18:   00000000    .word   0x00000000

0000001c <test3>:
  1c:   4b03        ldr r3, [pc, #12]   ; (2c <test3+0x10>)
  1e:   220f        movs    r2, #15
  20:   701a        strb    r2, [r3, #0]
  22:   f3bf 8f5f   dmb sy
  26:   7818        ldrb    r0, [r3, #0]
  28:   4770        bx  lr
  2a:   bf00        nop
  2c:   00000000    .word   0x00000000

Es ist offensichtlich das __DBM() fügt nur die ein dmb Anweisung und es dauert DMB2() um den Compiler tatsächlich dazu zu zwingen, die in den Registern zwischengespeicherten Werte zu löschen.

Ich glaube, ich habe einen CMSIS-Fehler gefunden.


5
2017-07-21 22:14



IMHO ist die CMSIS Version richtig.

Das Eingeben des Barrier-Befehls ohne den Speicher in der Clobber-Liste erreicht genau das, was er tun soll:

Wenn das vorherige Schreiben auf "x" Variable gepuffert wurde, wird es festgeschrieben. Dies ist beispielsweise dann nützlich, wenn Sie die Adresse "x" an eine DMA-Adresse übergeben möchten oder wenn Sie MPU einrichten möchten.

Es hat keine Auswirkung auf die Rückgabe von "x" (Ihr Programm ist garantiert korrekt, auch wenn Sie die Speicherbarriere weglassen).

Auf der anderen Seite, durch Einfügen von Speicher in Clobber-Liste, haben Sie keine Auswirkungen in Situationen wie das Beispiel zuvor (DMA, MPU ..).

Der einzige Unterschied im letzteren Fall besteht darin, dass wenn Sie zum Beispiel eine ISR haben, die den Wert von "x" direkt nach "strb" ändert, der Wert, der zurückgegeben wird, der vom ISR modifizierte Wert ist, weil der Clobber den Compiler verursacht hat aus dem Speicher zu lesen, um sich erneut zu registrieren. Aber wenn Sie dieses Ding erhalten möchten, sollten Sie "flüchtige" Variablen verwenden.

Mit anderen Worten: Die Barriere erzwingt Cache-Speicher-Speicher-Commit, um die Konsistenz mit anderen HW-Ressourcen zu gewährleisten, die auf den RAM-Speicher zugreifen könnten, während Clobbering-Speicher den Compiler daran hindert, den Speicher nicht zu ändern und in lokalen Registern wieder zu lesen Sache mit anderen Zwecken (es ist egal, ob eine Speicheränderung noch im Cache ist oder bereits im RAM festgeschrieben wurde, weil eine eventuelle Asm-Ladeoperation garantiert in beiden Fällen ohne Hindernisse funktioniert).


2
2018-04-19 13:12