我在32位Cortex-M3 ARM控制器(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′.
最佳答案 根据ARMv7m参考手册,LDRD不保证原子性. (A3.5.1)
The only ARMv7-M explicit accesses made by the ARM processor which exhibit single-copy atomicity are:
• All byte transactions
• All halfword transactions to 16-bit aligned locations
• All word transactions to 32-bit aligned locations
LDM, LDC, LDRD, STM, STC, STRD, PUSH and POP operations are seen to be a sequence of 32-bit
transactions aligned to 32 bits. Each of these 32-bit transactions are guaranteed to exhibit single-copy
atomicity. Sub-sequences of two or more 32-bit transactions from the sequence also do not exhibit
single-copy atomicity
您可以做的是使用一个字节向ISR指示您正在阅读它.
non_isr(){
do{
flag = 1
foo = doubleword
while(flag > 1)
flag = 0
}
isr(){
if(flag == 1)
flag++;
doubleword = foo
}
来源(需要登录):
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0403e.b/index.html