原子アクセスを確実にするには、割り込みを無効にする必要があります。他のプロセスがその変数にアクセスし、その変数を読んでいる間にその変数を変更する必要はありません。
Introduction to Embedded Computingから:
アトミックアクセス
このシナリオを想像してみての必要性:フォアグラウンドプログラムを、16ビットの変数を検討する必要が 8ビットのuC、上で実行して、それを呼び出すXしたがって、それは高い バイトをロードし、その後、下位バイトをロードします(または、逆の順序で、 の順番は関係ありません)。そして、16ビット値を調べます。今度は、その16ビット変数を変更する関連するISRとの 割り込みを想像してください。 さらに、変数の値は、プログラム実行の所定の時刻に で0x1234になることを想像してください。 、
- フォアグラウンド負荷の高いバイト(0x12を)
- ISRが発生し
- フォアグラウンドプログラムが見0xABCDと
- フォアグラウンド負荷の低いバイト(0xCD)にXを変更します。ここで発生する可能性が非常に悪いこと です0x12CDの16ビット値。
問題は、データのはずの不可分の一部、私たちの 変数Xは、実際に変数にアクセスするためのCPU命令が割り切れたので、 にアクセスする過程で変更されたということです。 したがって、変数Xの負荷が壊れています。 変数の読み込み順序は問題ではないことがわかります。この例で の順序を逆にすると、変数は0x35CDではなく0xAB34として正しく読み取られていたはずです( )。いずれにしても、読み取られた値は、 の古い有効値(0x1234)でも新しい有効値(0xABCD)でもありません。
ISRで参照されたデータを書くことは、それほど優れていません。今回は、 フォアグラウンドプログラムがISRのために、以前の値0x1234の を書き込んだとし、新しい値0xABCDを書き込む必要があると仮定します。この場合 に、次のようにVBTである:
- 前景格納新しい上位バイト(0xAB)
- ISRが発生し、X
- 0xAB34
として前景ストアを読み取る新しい低バイト(0xCD)
再度コード(今回はISR)は、以前の の有効値0x1234も新しい有効値0xABCDも認識せず、無効な値0xAB34の を認識しません。
spiTxRxByteCount &= ~0x0100;
は、Cでは1つの命令のように見えるかもしれませんが、CPUに対して実際にはいくつかの命令です。 GCCでコンパイルされ、アセンブリのリストがそうのようになります。
57:atomic.c **** spiTxRxByteCount &= ~0x0100;
68 .loc 1 57 0
69 004d A1000000 movl _spiTxRxByteCount, %eax
69 00
70 0052 80E4FE andb $254, %ah
71 0055 A3000000 movl %eax, _spiTxRxByteCount
71 00
割り込みがで-間のこれらの命令のいずれかで来て、データを変更する場合は、あなたの最初のISRは、潜在的に間違った値を読み取ることができます。割り込みを無効にする必要があります。また、変数volatile
も宣言してください。
RTOSをお持ちの方は、なぜミューテックスを使用しないのですか? –
@ [このようにしてOS上でセマフォ操作を実装](http://www.mpi-sws.org/~druschel/courses/os/lectures/proc4.pdf) –