9

3.2カーネルを使用するARM9があります-すべてが正常に機能しているようです。最近、起動時にいくつかのGPIOラインに50msのパルスを追加するためのコードを追加するように求められました。パルス符号は問題ありません。予想通り、線が上下するのがわかります。思った通りに動かないのはudelay()機能です。ドキュメントを読むと、単位はマイクロ秒であると思いますが、ロジックアナライザーで測定すると短すぎました。だから私はついにこのコードを追加して50msを取得しました。

// wait 50ms to be sure PCIE reset takes
for (i=0;i<6100;i++) // measured on logic analyzer - seems wrong to me!!
{
   __udelay(2000); // 2000 is max
}

私はそれが好きではありませんが、それはうまくいきます。コードにはいくつかの奇妙な定数と命令がありudelayます。誰かがこれがどのように機能することになっているのかについて私に教えてもらえますか?このコードは、すべてのクロックが初期化された後に呼び出されるため、他のすべては問題ないようです。

4

1 に答える 1

4

このスレッドの Linus によると:

1%オフくらいなら大丈夫です。誰かが遅延の小さなエラーに敏感な遅延値を選択した場合、または 5% のようなエラーにさえ気付いた場合、選択した遅延は短すぎます。

udelay() は、ある種の精密機器を意図したものではありませんでした。特に CPU が異なる周波数で実行されている場合、歴史的にかなり大きな変動がありました。従来のビジー ループは、割り込みだけでなく、キャッシュ アラインメント (以前はインライン化していました) などの影響も受けます。その後、TSC ベースのループは、明らかに TSC が安定しているかどうかに依存していました (これは、その間)。

歴史的に、udelay() が本当にオフ (つまり 50% オフなど) であるのを見てきました。1% の範囲のことについては心配しません。

ライナス

だから完璧にはなりません。オフになります。どれだけ多くの要因に依存しています。forループを使用する代わりに、代わりに使用することを検討してくださいmdelay。もう少し正確かもしれません。O'Reilly Linux Device Drivers bookから:

udelay呼び出しは、 の精度がわずか 8 ビットであり、長い遅延を計算すると顕著なエラーが累積するため、短い時間の経過に対してのみ呼び出す必要がありますloops_per_second最大許容遅延はほぼ 1 秒ですが (遅延が長くなると計算がオーバーフローするため)、udelayの推奨最大値は 1000 マイクロ秒 (1 ミリ秒) です。関数mdelayは、遅延が 1 ミリ秒より長くなければならない場合に役立ちます。

udelayはビジー待機関数であることを覚えておくことも重要です (したがって、 mdelayもそうです)。タイムラプス中は他のタスクを実行できません。したがって、特にmdelayを使用する場合は十分に注意し、目的を達成する方法が他にない場合を除き、使用を避ける必要があります。

現在、数マイクロ秒より長く、タイマー ティックより短い遅延のサポートは非​​常に非効率的です。遅延は、人間またはハードウェアが気付くのに十分な長さである必要があるため、これは通常は問題になりません。100 分の 1 秒は、人間に関連する時間間隔に適した精度ですが、1 ミリ秒は、ハードウェア アクティビティの十分な長さの遅延です。

具体的には、「udelayの推奨最大値は 1000 マイクロ秒 (1 ミリ秒)です」という行が突き出ています。これは、2000 が最大であると述べているためです。遅延の挿入に関するこのドキュメントから:

mdelay は udelay のマクロ ラッパーで、大きな引数を udelay に渡すときにオーバーフローの可能性を考慮します。

そのため、オーバーフロー エラーが発生している可能性があります。私は通常、2000年が「大きな議論」であるとは考えていません.

しかし、タイミングに本当の精度が必要な場合は、自分が持っているようにオフセットを処理するか、独自にロールするか、別のカーネルを使用する必要があります。アセンブラーまたはハード リアルタイム カーネルを使用して独自の遅延関数をロールする方法については、高解像度タイミングに関するこの記事を参照してください。

参照: Linux カーネル: udelay() の戻りが早すぎる?

于 2012-11-16T14:31:31.950 に答える