arm – 读取cortex-m3上的64位易变量

我在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

不需要登录:
http://www.telecom.uff.br/~marcos/uP/ARMv7_Ref.pdf

点赞