gpt4 book ai didi

arm - 在 cortex-m3 上读取 64 位 volatile 变量

转载 作者:行者123 更新时间:2023-12-02 02:33:05 25 4
gpt4 key购买 nike

我在 32 位 Cortex-M3 ARM Controller (STM32L1) 上有一个 64 位整数变量,可以通过中断处理程序异步修改该变量。

volatile uint64_t v;
void some_interrupt_handler() {
v = v + something;
}

显然,我需要一种方法来访问它,以防止获得不一致的、半途更新的值。

这是第一次尝试

static inline uint64_t read_volatile_uint64(volatile uint64_t *x) {
uint64_t y;
__disable_irq();
y = *x;
__enable_irq();
return y;
}

CMSIS 内联函数 __disable_irq()__enable_irq() 有一个不幸的副作用,强制编译器出现内存屏障,所以我尝试提出更细粒度的东西

static inline uint64_t read_volatile_uint64(volatile uint64_t *x) {
uint64_t y;
asm ( "cpsid i\n"
"ldrd %[value], %[addr]\n"
"cpsie i\n"
: [value]"=r"(y) : [addr]"m"(*x));
return y;
}

它仍然禁用中断,这是不可取的,所以我想知道是否有一种方法可以在不诉诸cpsid的情况下做到这一点。 权威指南ARM Cortex-M3 和 Cortex-M4 处理器,第三版,作者:Joseph Yiu

If an interrupt request arrives when the processor is executing a multiple cycle instruction, such as an integer divide, the instruction could be abandoned and restarted after the interrupt handler completes. This behavior also applies to load double-word (LDRD) and store double-word (STRD) instructions.

这是否意味着我只要写下这个就可以了?

static inline uint64_t read_volatile_uint64(volatile uint64_t *x) {
uint64_t y;
asm ( "ldrd %[value], %[addr]\n"
: [value]"=&r"(y) : [addr]"m"(*x));
return y;
}

(使用 "=&r" 解决 ARM 勘误表 602117)

是否有一些库或内置函数可以实现相同的可移植性?我已在 stdatomic.h 中尝试过 atomic_load(),但由于 对“__atomic_load_8”的 undefined reference 而失败。

最佳答案

是的,在此应用程序中使用简单的 ldrd 是安全的,因为如果中断,它将重新启动(而不是恢复),因此从中断处理程序的角度来看,它看起来是原子的。

这更普遍地适用于所有加载指令,除了那些异常可继续的指令,这是一个非常有限的子集:

  • 只有 ldmpopvldmvpop 可以继续
  • it block 内的指令永远无法继续
  • 第一个加载的寄存器也是基址寄存器的 ldm/pop (例如 ldm r0, { r0, r1 })永远不会可继续

这为自动读取由同一核心上的中断处理程序修改的多字变量提供了很多选项。如果您希望读取的数据不是连续的单词数组,那么您可以执行以下操作:

1:      ldrex   %[val0], [%[ptr]]       // can also be byte/halfword
... more loads here ...
strex %[retry], %[val0], [%[ptr]]
cbz %[retry], 2f
b 1b
2:

对于 ldrex/strex 使用哪个字(或字节/半字)并不重要,因为异常将执行隐式 clrex

另一个方向,编写一个由中断处理程序读取的变量要困难得多。我不是 100% 确定,但我认为唯一保证对中断处理程序来说是原子的存储是那些“单副本原子”的存储,即单字节、对齐半字和对齐字。任何更大的事情都需要禁用中断或使用一些巧妙的无锁结构。

关于arm - 在 cortex-m3 上读取 64 位 volatile 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42651051/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com