首页 文章

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

提问于
浏览
4

我在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 就可以做到这一点 . Joseph Yiu的第三版ARM Cortex-M3和Cortex-M4处理器权威指南说

如果在处理器执行多周期指令(例如整数除法)时到达中断请求,则可以在中断处理程序完成后放弃并重新启动指令 . 此行为也适用于加载双字(LDRD)和存储双字(STRD)指令 .

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

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() ,但它失败了 undefined reference to '__atomic_load_8' .

1 回答

  • 1

    根据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

相关问题