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

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

**简介:**我设计了一个采用ATSAME54N20A 32位ARM® Cortex®-M4 F MCU的嵌入式系统。该板即将组装并准备好编程,因此我正在设置我的编程环境。我选择了一个裸机解决方案,其中只提供了最少的C语言编写的文件,因为尽管这是一个耗时的过程,但它有助于我了解系统的工作原理。所选的编译器是GCC,参数如下:

  1. "...\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
  2. ...
  3. "...\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行)

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

我不明白。我试着跟踪这些函数的实现,看看它们在做什么,最后得到了下面的代码:

  1. // ==============================================================================================
  2. // Enter critical section.
  3. // ==============================================================================================
  4. // Get primask
  5. register uint32_t __regPriMask __asm__("primask");
  6. uint32_t volatile *atomic = __regPriMask;
  7. // Disable IRQ interrupts by setting the I-bit in the CPSR.
  8. // Can only be executed in Privileged modes.
  9. __asm__ volatile ("cpsid i" : : : "memory");
  10. // Memory barrier
  11. do {\
  12. __asm__ volatile ("isb 0xF":::"memory");
  13. __asm__ volatile ("dmb 0xF":::"memory");
  14. __asm__ volatile ("isb 0xF":::"memory");
  15. } while (0U);
  16. // ==============================================================================================
  17. // 25.8.1 Control A
  18. // ==============================================================================================
  19. // NVMCTRL-> offset: CTRLA
  20. // 0x41004000U 0x00000000U
  21. (*(volatile uint32_t*)0x41004000U) = 0x01000400U;
  22. // ==============================================================================================
  23. // Leave critical section.
  24. // ==============================================================================================
  25. // Memory barrier
  26. do {\
  27. __asm__ volatile ("isb 0xF":::"memory");
  28. __asm__ volatile ("dmb 0xF":::"memory");
  29. __asm__ volatile ("isb 0xF":::"memory");
  30. } while (0U);
  31. // Set primask
  32. __regPriMask = &atomic;

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

brgchamk

brgchamk1#

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

相关问题