Барьеры памяти для критических секций при запуске MCU Cortex-M4F - PullRequest
0 голосов
/ 24 июня 2018

ВВЕДЕНИЕ: Я разработал встроенную систему с ATSAME54N20A 32-разрядным микроконтроллером ARM® Cortex®-M4F. Вскоре плата будет собрана и готова к программированию, поэтому я настраивал свою среду программирования. Я выбрал простое решение, в котором присутствуют только минимальные необходимые C-записанные файлы, потому что, хотя это трудоемкий процесс, он помогает мне понять работу системы. Выбранный компилятор GCC со следующими аргументами:

"...\arm-none-eabi-gcc.exe"  -x c -mthumb -O1 -ffunction-sections -mlong-calls -g3 -Wall -mcpu=cortex-m4 -c -std=gnu99 main.c -o main.o

...

"...\arm-none-eabi-gcc.exe" weak_handlers.o main.o SEGGER_RTT.o SEGGER_RTT_printf.o SEGGER_RTT_Syscalls_GCC.o -mthumb -Wl,-Map="app.map" -Wl,--start-group -lm  -Wl,--end-group -Wl,--gc-sections -mcpu=cortex-m4 -T flash.ld -o app.elf

ВОПРОС: В проекте эталонного программирования, с которым я сравниваю свой код (например, Atmel Studio LEDflasher ), используются критические разделы, подобные следующим: (присутствует в строке hri_nvmctrl_e54.h) 944)

NVMCTRL_CRITICAL_SECTION_ENTER();
((Nvmctrl *)hw)->CTRLA.reg |= NVMCTRL_CTRLA_RWS(mask);
NVMCTRL_CRITICAL_SECTION_LEAVE();

Что я не понимаю. Я попытался проследить эти реализации функций, чтобы увидеть, что они делают, и получил следующий код:

// ==============================================================================================
// Enter critical section.
// ==============================================================================================
// Get primask
register uint32_t __regPriMask         __asm__("primask");
uint32_t volatile *atomic = __regPriMask;
// Disable IRQ interrupts by setting the I-bit in the CPSR.
// Can only be executed in Privileged modes.
__asm__ volatile ("cpsid i" : : : "memory");
// Memory barrier
do {\
        __asm__ volatile ("isb 0xF":::"memory");
        __asm__ volatile ("dmb 0xF":::"memory");
        __asm__ volatile ("isb 0xF":::"memory");
} while (0U);


// ==============================================================================================
// 25.8.1 Control A
// ==============================================================================================
// NVMCTRL->     offset: CTRLA
// 0x41004000U           0x00000000U  
(*(volatile uint32_t*)0x41004000U) = 0x01000400U;


// ==============================================================================================
// Leave critical section.
// ==============================================================================================
// Memory barrier
do {\
        __asm__ volatile ("isb 0xF":::"memory");
        __asm__ volatile ("dmb 0xF":::"memory");
        __asm__ volatile ("isb 0xF":::"memory");
} while (0U);
// Set primask
  __regPriMask = &atomic;

Имеет ли смысл какой-либо из этих барьеров памяти? Заворачивает a asm volatile ("dmb 0xF" ::: "memory"); между двумя asm volatile ("isb 0xF" :: : "память"); распространенная полезная реализация? Что бы означали эти инструкции? Я не уверен, что путь "Реализация GoTo" был соблюден правильно, чтобы в конечном итоге с этими утверждениями!

Я хотел бы заранее поблагодарить всех за ваше время и надеюсь, что этот вопрос поможет другим в будущем!

1 Ответ

0 голосов
/ 25 июня 2018

Имеет ли смысл какой-либо из этих барьеров памяти?

В моих глазах да. При наличии кешей, прерываний, оптимизаций, задержек загрузки и т. Д. Может потребоваться запрет памяти.

Упаковывает asm volatile ("dmb 0xF" ::: "memory"); между двумя asm volatile ("isb 0xF" ::: "memory"); общая полезная реализация? Что означают эти инструкции?

isb: пока что очищает буферы и извлекает инструкции.

dmb: на данный момент завершен весь доступ к памяти.

isb: после dmb он гарантирует, что новый контекст был загружен.

Это полезный и очень безопасный (и оборонительный) способ защиты кода от переупорядочения процессора / компилятора, задержек и т. Д.

Кроме того, эта критическая область отключает прерывания для того, чтобы продвинуть их к задаче с наивысшим приоритетом, поэтому никто не сможет прервать эту часть кода. Определенно, правильный способ защитить критическую область.

...