Барьер памяти данных (DMB) в библиотеках CMSIS для Cortex-M3s - PullRequest
5 голосов
/ 19 июля 2011

В определениях CMSIS для gcc вы можете найти что-то вроде этого:

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

Мой вопрос: как использовать барьер памяти, если он не объявляет «память» в списке клобберов?

Это ошибка в core_cm3.h или есть причина, по которой gcc должен вести себя правильно без какой-либо дополнительной помощи?

Ответы [ 2 ]

5 голосов
/ 22 июля 2011

Я провел некоторое тестирование с помощью gcc 4.5.2 (созданной с помощью LTO). Если я скомпилирую этот код:

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;
}

используя arm-none-eabi-gcc -Os -mcpu=cortex-m3 -mthumb -c dmb.c, затем из arm-none-eabi-objdump -d dmb.o я получаю это:

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

Очевидно, что __DBM() вставляет только инструкцию dmb и требуется DMB2(), чтобы фактически заставить компилятор сбрасывать значения, кэшированные в регистрах.

Я думаю, что нашел ошибку CMSIS.

2 голосов
/ 19 апреля 2013

ИМХО версия CMSIS верна.

Внедрение инструкции барьера без памяти в списке клоббера позволяет добиться именно того, для чего она предназначена:

Если предыдущая запись в переменную "x" была буферизована, она фиксируется Это полезно, например, если вы собираетесь передать адрес «x» в качестве адреса DMA или если вы собираетесь настроить MPU.

Не влияет на возвращение "x" (ваша программа гарантированно будет правильной, даже если вы пропустите барьер памяти).

С другой стороны, вставив память в список клобберов, вы не получите никакого эффекта в ситуациях, подобных предыдущему (DMA, MPU ..).

Единственное отличие в последнем случае состоит в том, что если у вас есть, например, ISR, изменяющий значение «x» сразу после «strb», то возвращаемое значение будет значением, измененным ISR, потому что clobber заставил компилятор читать из памяти, чтобы зарегистрироваться снова. Но если вы хотите получить эту вещь, то вам следует использовать «изменчивые» переменные.

Другими словами: барьер сил кеша против фиксации памяти, чтобы гарантировать согласованность с другими ресурсами HW, которые могут получить доступ к памяти RAM, в то время как сгущение памяти приводит к тому, что компилятор останавливается, предполагая, что память не изменилась, и снова читает в локальных регистрах, это другое дело с другими целями (не имеет значения, если изменение памяти все еще находится в кеше или уже зафиксировано в оперативной памяти, потому что возможная операция загрузки asm гарантированно будет работать в обоих случаях без барьеров).

...