繁体   English   中英

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

[英]Memory barriers for critical sections in Cortex-M4F MCU startup

简介:我设计了一个嵌入式系统,该系统具有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示例 )使用的关键部分如下所示:(出现在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 volatile(“ dmb 0xF” :::“内存”); 在两个asm volatile之间(“ isb 0xF” :::“内存”); 一个常见的有用实现? 这些指示是什么意思? 我不确定是否正确遵循了“ GoTo实现”路径以结束这些语句!

我想在此先感谢大家的宝贵时间,并希望这个问题对以后的其他人有所帮助!

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

在我眼中,是的。 如果存在缓存,中断,优化,加载等待时间等,则可能必须使用内存屏障。

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

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

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

isb :后dmb ,它保证了新的环境已经加载。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM