32ビットのCortex-M3 ARMコントローラ(STM32L1)に64ビットの整数変数があります。これは割り込みハンドラで非同期に変更できます。cortex-m3で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プロセッサ、第3版は
言います割り込みハンドラ が完了した後で、命令 を破棄して再起動することができます。この現象は、ロードダブルワード(LDRD)と ストアダブルワード(STRD)命令にも適用されます。
これは単にこれを書いてうまくいくということですか?
(ARMエラッタ602117を回避するために"=&r"
を使用した)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;
}
同じ移植性を行い、いくつかのライブラリや組み込み関数はありますか?私はstdatomic.h
にatomic_load()
を試しましたが、それはundefined reference to '__atomic_load_8'
で失敗します。
、そしてちょうどLDRDを使用すると、yesと動作するはずです(割り込みの有効/無効を混乱させることなく)?一方の側がもう一方の側を使用するようにしてください。または、strd/ldrdを使いたくない場合は、strex/ldrexを試すこともできます。 –
'strd'を使うと' ldrd'を中断できないので、別のセマフォが必要なので 'strex'のチェックで遅延や複雑さが増えます。 – berendi
よくあなたはあなたが最後に読んだものを指示し、割り込みが他のものを変更してからスワップすることを指定するping/pongメールボックス取引の何らかの仕掛けをすることができます... –