assembly Cortex-M4 F MCU启动时临界区的存储器屏障

xuo3flqw  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(245)

**简介:**我设计了一个采用ATSAME54N20A 32位ARM® Cortex®-M4 F MCU的嵌入式系统。该板即将组装并准备好编程,因此我正在设置我的编程环境。我选择了一个裸机解决方案,其中只提供了最少的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;

这些内存障碍有意义吗? Package aasm是易失性的吗? 在两个asmvolatile(“isb 0xF”:::“内存”)之间; 一个常见的有用的实现?这些指令是什么意思?我不确定是否正确地遵循了“后藤实现”路径,以这些语句结束!
我想提前感谢大家的时间,并希望这个问题有助于其他人在未来!

brgchamk

brgchamk1#

这些记忆障碍有意义吗?
在我看来,是的。如果有缓存,中断,优化,加载延迟等,内存障碍可能是必须的。
正在 Package 一个asm volatile(“dmb 0xF”:::“内存”);在两个asm volatile(“isb 0xF”:::“内存”)之间;一个常见的有用的实现?那些指令是什么意思?
isb:它刷新缓冲区并提取到目前为止的指令。
dmb:它完成到目前为止的所有存储器访问。
isb:在dmb之后,它确保已经加载了新的上下文。
这是一种非常有用且非常安全(和防御性)的方法,可以保护代码免受处理器/编译器重新排序、延迟等的影响。
此外,这个关键区域禁止中断,以便将其提升到最高优先级任务,因此没有人能够中断这部分代码。当然,这是保护关键区域的正确方法。

相关问题