私は信号を生成する 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 にはフラッシュ プリフェッチがあります。)