5

私は信号を生成する STM32F4 CPU のプロジェクトに取り組んでいます。

STM32 の CPU クロック (プリスケーラなし) に汎用タイマーを使用して、オーバーフロー時に割り込みをトリガーし、その後 GPIO で定期的な信号を生成します。

非常に正確な時間 (基本的には 1 CPU サイクルの精度まで) に GPIO をトリガーする必要があります。優先度 & al を設定することで、このジッターを +-5 サイクルに減らすことができましたが、CPU の動作によっては、このジッターが存在します。

この数サイクルのジッターを補正する必要があります。正確なタイミングで GPIO を切り替える限り、数サイクルの遅延を追加しても問題はありません。

私の考えは、カウンターの現在の値を読み取り、FIXED_NUMBER-CURRENT_VALUE 時間のアクティブなループを作成して、正確な時間にループを終了できるようにすることでした。

ただし、C で単純なループを実行する - FOR ループ、または while(counter->value < TARGET) は、ジッターを減らす代わりに追加するため、機能しません。

私は何か間違ったこと/素朴なことをしていますか? アセンブリで行う必要がありますか?それはCとどのように違うでしょうか(GCCで逆アセンブリをチェックして、ループが最適化されていないか、メモリにヒットしていないかを確認しましたか?)

(私は空の、最適化されていないがメモリループ本体に当たらないことを保証しました)

編集: AVRでこの例を参照してください (私が知っているより安定しています)

edit2 : 次のようなアセンブリで単純なループを試しました (r0 は私のカウンター、待機するサイクル数、レジスター内)

loop : SUBS r0,#1 ; tried with 2 also
       BGE loop

繰り返しますが、ジッタはそれがない方が優れています。

要するに、私はどれだけ遅らせるべきかをすでに知っています。コードのブランチが確実にNサイクルを消費し、別のケースではMサイクルを消費する方法が必要です。残念ながら、パイプラインのリフィルには信頼できるサイクル数がかかるように見えないため、分岐だけでは機能しないようです。また、条件式も常に同じサイクル数を取るため (何もしない場合もあります)、そうではありません。

フラッシュの代わりに RAM から実行すると、一貫性が向上しますか? (NB stm32f4 にはフラッシュ プリフェッチがあります。)

4

2 に答える 2

9

(応答遅延の短縮に関する質問の回答が得られるまでに 3 年かかったというのは皮肉なことです。)

+/- 5 サイクルは非常になじみ深い音です。割り込みディスパッチ中にフラッシュ コントローラにアクセスする待機状態になっている可能性があります。

CPU は、割り込みディスパッチ中に次の 3 つのことを行う必要があります。

  1. ベクター テーブル エントリをロードします。
  2. 割り込みルーチンの初期コードをロードします。
  3. いくつかのレジスタをスタックに書き込みます。

ベクタ テーブルや割り込みルーチン コードが Flash にある場合、項目 1 と 2 のフェッチは Flash に行われます。CPU を最高定格速度 (最大 168MHz) で実行している場合、フラッシュへのアクセスには 5 つの待機状態が伴います。これは、要求されたデータがフラッシュ キャッシュにあるかどうかに応じて、フラッシュへのアクセスに 1 サイクルまたは 6 サイクルかかることを意味します。正確に0 または 5 サイクルのレイテンシが発生している場合は、これが原因である可能性があります。この問題は、ISR コードとベクター テーブルを RAM に移動することで簡単に修正できます。Flash キャッシュを無効にすることで「修正」することもできます。これにより、Flash アクセスが予想どおり遅くなります。

さらに厄介な要因があります。割り込み対象のコードがFlash も使用している場合、割り込みのディスパッチは Flash アクセスが完了するのを待たなければならない可能性があります。中断されたコードを RAM に移動することでもこれを修正できますが、この時点では、Flash には何も存在しないように聞こえ始めています。以下で説明するように、コードを Flash に保持する方法があります。

最後に、さらに厄介なことがあります: レイテンシーに敏感な割り込みの直前に発生する可能性のある他の割り込みがある場合、その割り込みはテール チェインにより -5 サイクルのレイテンシーを得る可能性があります。

リストした 2 番目の 2 つの問題に対する私の解決策は少し奇妙です。割り込みが発生したときに、プロセッサがアイドル状態であることを確認してください。私がこれを行った方法は、(タイマーを使用して) 遅延に敏感な割り込みの直前に優先度の低い割り込みが到着するように構成することです。その ISR は、単に割り込み待ち命令を実行しwfiます。

これらは克服可能な問題です。Cを放棄してアセンブリ言語で書く必要があるというコメント者には同意しません。私のm4vgalibシステムには、アセンブリ言語がほとんど含まれておらず、ジッターが非常に低くなっています。

私のブログの記事の 1 つのセクションで、これらのまったく同じ問題と解決策について詳しく説明しています。

于 2015-06-12T17:20:10.353 に答える