ber*_*ing 5 arm atomic interrupt cortex-m3 stm32
我有一个32位的Cortex-M3 ARM控制器(STM32L1),其可以通过异步中断处理程序来修改在64位整数的变量。
volatile uint64_t v;
void some_interrupt_handler() {
v = v + something;
}
Run Code Online (Sandbox Code Playgroud)
显然,我需要一种访问方式,以防止获取不一致的中途更新值。
这是第一次尝试
static inline uint64_t read_volatile_uint64(volatile uint64_t *x) {
uint64_t y;
__disable_irq();
y = *x;
__enable_irq();
return y;
}
Run Code Online (Sandbox Code Playgroud)
该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;
}
Run Code Online (Sandbox Code Playgroud)
它仍然禁用中断,这是不希望的,因此我想知道是否有一种方法可以不诉诸cpsid。该权威指南的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;
}
Run Code Online (Sandbox Code Playgroud)
("=&r"用于解决ARM勘误表602117)
是否有一些可移植的库或内置函数呢?我已经试过atomic_load()了stdatomic.h,但是失败了undefined reference to '__atomic_load_8'。
根据 ARMv7m 参考手册,LDRD 不保证原子性。(A3.5.1)
\n\nThe only ARMv7-M explicit accesses made by the ARM processor which exhibit single-copy atomicity are:\n\n\xe2\x80\xa2 All byte transactions\n\n\xe2\x80\xa2 All halfword transactions to 16-bit aligned locations\n\n\xe2\x80\xa2 All word transactions to 32-bit aligned locations\n\nLDM, LDC, LDRD, STM, STC, STRD, PUSH and POP operations are seen to be a sequence of 32-bit\ntransactions aligned to 32 bits. Each of these 32-bit transactions are guaranteed to exhibit single-copy\natomicity. Sub-sequences of two or more 32-bit transactions from the sequence also do not exhibit\nsingle-copy atomicity\nRun Code Online (Sandbox Code Playgroud)\n\n您可以做的是使用一个字节向 ISR 指示您正在读取它。
\n\nnon_isr(){\n do{\n flag = 1\n foo = doubleword\n while(flag > 1)\n flag = 0\n}\n\nisr(){\n if(flag == 1) \n flag++;\n doubleword = foo\n}\nRun Code Online (Sandbox Code Playgroud)\n\n来源(需要登录):\n http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0403e.b/index.html
\n\n不需要登录:\n http://www.telecom.uff.br/~marcos/uP/ARMv7_Ref.pdf
\n| 归档时间: |
|
| 查看次数: |
764 次 |
| 最近记录: |