0

私は2つの配列を持っています。そして、他の配列の値のいくつかに従って、配列の1つを更新しているmain内の関数を呼び出しています。

volatile float32_t raw_data[3]; //this is being updated by an interrupt handler
void get_acc(int32_t* acc_data, float32_t* raw_data)
{
  acc_data[0] = (raw_data[0] - OFFSETX)/SENSX; //OFFSETX and SENSX defined as a macro
  acc_data[1] = (raw_data[1] - OFFSETY)/SENSY;
  acc_data[2] = (raw_data[2] - OFFSETZ)/SENSZ;
}
int main()
{
  int32_t acc_data[3];      
  int32_t data_ready = 0;  //being updated by interrupt handler
  while(1)
  {
  if(data_ready)
  get_acc(acc_data,raw_data);
  }
}

私の絶対的なショックに、ブレークポイントを使用して get_acc をステップスルーする変数を見ると、最初の acc_data[0] のみが更新され、他のすべては実行されても 0 に設定されます。今私の最初の疑惑は、おそらくアドレスが適切に更新されていないポインタに関連するものです。手動ではなく、 for ループ内で配列インデックスを更新した場合と同じように、配列を渡すことを使用したためです。誰が何が間違っているのか洞察を与えることができますか?

4

2 に答える 2

2

おそらく微妙な同期エラーがここにあります:

  1. ジョナサンが指摘したようraw_dataに、関数内で修飾子が失われました。このような方法で変数を使用するvolatileことは、シグナル ハンドラが含まれていなくても未定義の動作です。
  2. さらに、データはシグナルハンドラーによって非同期に処理されているようです。C99 の時点で、このようなシグナル ハンドラを使用できる唯一のデータ型は ですsig_atomic_t。C11 はもう少し進んで、他のロックフリーのアトミック型も許可します。

抽象マシンの処理がシグナルの受信によって中断されると、浮動小数点環境の状態と同様に、ロックフリーのアトミック オブジェクトでも型 volatile sig_atomic_t でもないオブジェクトの値は未指定になります。ハンドラーによって変更された、ロックフリーのアトミック オブジェクトでもタイプ volatile sig_atomic_t でもないオブジェクトの値は、ハンドラーによって変更され、復元されない場合の浮動小数点環境の状態と同様に、ハンドラーが終了すると不確定になります。元の状態に。

ご覧のとおり、特に浮動小数点に触れることは禁止されています。

于 2012-10-21T14:21:41.460 に答える
1

コード (Mac OS X 10.7.5 上の GCC 4.7.1) をコンパイルすると、次の警告が表示されます。

warning: passing argument 2 of ‘get_acc’ discards ‘volatile’ qualifier from pointer target type [enabled by default]
note: expected ‘float32_t *’ but argument is of type ‘volatile float32_t *’

これがあなたの問題の原因かどうかはわかりませんが、それが要因かもしれません。data_readyまた、volatile資格を取得する必要があることに注意してください。

また、 でコンパイルすると-Wshadow、次のようになります。

In function ‘get_acc’:
warning: declaration of ‘raw_data’ shadows a global declaration [-Wshadow]

これは、より深刻な問題というよりも、「誤解のリスク」の問題です。

ただし、修飾子の違いは別として、表示するコードはクリーンであり、コンパイラは から 3 つの値を読み取りraw_data、それらを に処理するコードを生成する必要がありますacc_data。関数用に生成されたアセンブリ言語を見ましたか?

于 2012-10-21T13:55:45.233 に答える