2012-11-28 7 views
7
static void RadioReleaseSPI(void) { 
    __disable_interrupt(); 
    spiTxRxByteCount &= ~0x0100; 
    __enable_interrupt(); 
} 

私は、複数のタスクがSPIリソースを使用しようとしていることを理解しています。 spiTxRxByteCountは、SPIが現在別のタスクによって使用されているかどうかを追跡するために使用されるグローバル変数です。タスクがSPIを必要とする場合、spiTxRxByteCountのステータスをチェックして、SPIが使用されているかどうかを確認できます。 SPIを使用してタスクが完了すると、この関数を呼び出してビットをクリアし、SPIが現在解放されていることを示します。しかし、なぜ割り込みを最初に無効にしてから、再度有効にするのですか?ちょっとパラノイア?ここで割り込みを無効にするのはなぜですか?

+0

RTOSをお持ちの方は、なぜミューテックスを使用しないのですか? –

+0

@ [このようにしてOS上でセマフォ操作を実装](http://www.mpi-sws.org/~druschel/courses/os/lectures/proc4.pdf) –

答えて

14

& =はアトミックではありませんが、リード・モディファイ・ライト・オペレーションを行います。途中で割り込みが変化して、誤った値で上書きされてしまうことはありません。

8

原子アクセスを確実にするには、割り込みを無効にする必要があります。他のプロセスがその変数にアクセスし、その変数を読んでいる間にその変数を変更する必要はありません。

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も宣言してください。