Cortex-M4F MCU启动中关键部分的存储屏障

时间:2018-06-23 23:01:10

标签: c assembly arm inline-assembly memory-barriers

简介:我设计了一个嵌入式系统,该系统具有ATSAME54N20A 32位ARM®Cortex®-M4FMCU。该板将被组装并准备好进行编程,因此我正在设置编程环境。我选择了一种准系统解决方案,其中仅包含最少的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 example)使用如下所示的关键部分:(出现在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;

这些内存障碍是否有意义?在两个 asm 易失性(“ isb 0xF”之间包装 a asm 易失性(“ dmb 0xF” :::“内存”); “ :::”内存“); 常见的有用实现?这些指示是什么意思?我不确定是否正确遵循了“ GoTo实现”路径以结束这些语句!

我想在此先感谢大家,希望这个问题对以后有帮助!

1 个答案:

答案 0 :(得分:0)

  

这些记忆障碍是否有意义?

在我眼中,是的。如果存在缓存,中断,优化,加载延迟等,则可能必须要有内存屏障。

  

正在包装一个asm volatile(“ dmb 0xF” :::“ memory”);在两个asm volatile之间(“ isb 0xF” :::“内存”);一个常见的有用实现?这些指示是什么意思?

isb:到目前为止,它会刷新缓冲区并提取指令。

dmb:到目前为止,它完成了所有内存访问。

isb:在dmb之后,它确保新上下文已加载。

这是一种保护代码免受处理器/编译器重新排序,延迟等影响的有用且非常安全(防御性)的方法。

此外,此关键区域正在禁用中断,以将其提升为最高优先级的任务,因此没有人能够中断代码的这一部分。绝对是保护关键区域的正确方法。

相关问题