I have a 64-bit integer variable on a 32-bit controller of a Cortex-M3 ARM controller (STM32L1) that can be changed asynchronously using an interrupt handler.
volatile uint64_t v;
void some_interrupt_handler() {
v = v + something;
}
Obviously, I need a way to access it in such a way as to prevent getting inconsistent, full updated values.
Here is the first attempt
static inline uint64_t read_volatile_uint64(volatile uint64_t *x) {
uint64_t y;
__disable_irq();
y = *x;
__enable_irq();
return y;
}
CMSIS built-in functions __disable_irq()also __enable_irq()have an unpleasant side effect, causing a memory barrier in the compiler, so I tried to come up with something finer
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;
}
It still disables interrupts, which is undesirable, so I wonder if there is a way to do this without resorting to cpsid. The Ultimate Guide to ARM Cortex-M3 and Cortex-M4 Processors, Third Edition of Joseph Yiu Say
, , , . (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)
- , ? atomic_load() stdatomic.h, undefined reference to '__atomic_load_8'.