先月、割り込みを使用してUART(MIDI用)をSTM(STM32F103C8T6)と連携させるのに多くの時間を費やしましたが、あまり成功しませんでした。
ただし、DMAを使用した今晩は非常に高速に動作しました。
私が読む限りDMAはより高速でCPUを解放するので、なぜ割り込みを優先して常にDMAを使用しないのですか?特にSTM32ではかなりの問題があるようです。
STM32CubeMx / HALを使用しています。
先月、割り込みを使用してUART(MIDI用)をSTM(STM32F103C8T6)と連携させるのに多くの時間を費やしましたが、あまり成功しませんでした。
ただし、DMAを使用した今晩は非常に高速に動作しました。
私が読む限りDMAはより高速でCPUを解放するので、なぜ割り込みを優先して常にDMAを使用しないのですか?特にSTM32ではかなりの問題があるようです。
STM32CubeMx / HALを使用しています。
回答:
DMAはCPUを解放するため、同じコアで実行されている他の割り込み駆動型アプリケーションのレイテンシを削減する可能性がありますが、それに関連するコストがあります。
唯一の存在であるDMAチャネルの限られた量は、これらのチャネルが異なる周辺機器とやり取りする方法には制限があります。同じチャネル上の別のペリフェラルは、DMAの使用により適している場合があります。
たとえば、5msごとに大量のI2C転送がある場合、これは、UART2に時々到着するデバッグコマンドよりもDMAのより良い候補のようです。
DMAの設定と維持はそれ自体コストがかかります。(通常、DMAの設定は、通常の文字単位の割り込み駆動型転送の設定よりも複雑であると考えられます。これは、メモリ管理、関連する周辺機器、割り込み自体を使用するDMA、およびDMAの外側で最初の数文字を解析する必要があるためです。とにかく、以下を参照してください。)
DMAは、クロックを供給する必要があるコアのドメインであるため、追加の電力を使用する場合があります。一方、コアがサポートしている場合は、DMA転送の進行中にCPUを一時停止できます。
DMAを使用するには、メモリバッファーが必要です(周辺機器間DMAを実行している場合を除く)。そのため、それに関連するメモリコストが発生します。
(メモリコストは、文字ごとの割り込みを使用する場合にも存在する可能性がありますが、メッセージが割り込み内ですぐに解釈される場合は、はるかに小さくなるか、まったくなくなる場合があります。)
転送が完了または半分完了したときにのみCPUに通知されるため、DMAはレイテンシを生成します(他の回答を参照)。
リングバッファーとの間でデータをストリーミングする場合を除いて、受信/送信するデータの量を事前に知っておく必要があります。
これは、文字ごとの割り込みを使用してメッセージの最初の文字を処理する必要があることを意味する場合があります。たとえば、XBeeとのインターフェースをとるときは、最初にパケットタイプとサイズを読み取ってから、割り当てられたバッファーへのDMA転送をトリガーします。
他のプロトコルでは、メッセージの終わりの区切り文字のみを使用する場合、これはまったく不可能である可能性があります。たとえば、'\n'
区切り文字として使用するテキストベースのプロトコル。(DMAペリフェラルが文字のマッチングをサポートしていない場合)。
ご覧のとおり、ここでは考慮すべき多くのトレードオフがあります。一部はハードウェアの制限(チャネル数、他の周辺機器との競合、文字の一致)に関連し、一部は使用するプロトコル(区切り文字、既知の長さ、メモリバッファー)に基づいています。
事例証拠を追加するために、私は非常に異なるプロトコルで多くの異なる周辺機器を使用する趣味のプロジェクトでこれらのトレードオフのすべてに直面しました。主に「転送するデータの量と転送する頻度」という質問に基づいて、いくつかのトレードオフがありました。これは基本的に、CPUに対する単純な割り込み駆動型転送の影響の大まかな見積もりを提供します。このため、同じDMAチャネルを使用するUART転送を数秒ごとに行うよりも、5msごとに前述のI2C転送を優先しました。別のUART転送がより頻繁に行われ、その一方でより多くのデータを使用すると、まれにしか発生しない別のI2C転送よりも優先されます。それはすべてトレードオフです。
もちろん、DMAを使用することにも利点がありますが、それはあなたが要求したものではありません。
通常、DMAを使用すると、すべての文字で割り込みが発生するのではなく、文字の「バッファーフル」が受信(または送信)された後でのみ、割り込みが発生します。これにより、これらの文字の処理のレイテンシが増加します。最初の文字は、バッファ内の最後の文字が受信されるまで処理されません。
このレイテンシは、特にMIDIなどのレイテンシの影響を受けやすいアプリケーションでは、数ミリ秒かかるため、ライブパフォーマンスで深刻な演奏性の問題が発生する可能性があるため、好ましくない場合があります。
DMAは割り込みの代わりにはなりません-それらは通常一緒に使用されます!たとえば、DMAを使用してUART経由でデータを送信している場合でも、送信が完了したことを通知する割り込みが必要です。
DMAを使用すると、UARTペリフェラルの使用に関する他のすべての考慮事項を超える興味深い質問と課題が生じます。いくつか例を挙げましょう。あなたのuCが他のデバイスと一緒にRS485(または何でも)バスに座っていると仮定します。バス上には多くのメッセージがあり、いくつかはあなたのuCを対象としていますが、そうでないものもあります。さらに、これらのバスネイバーはすべて異なるデータプロトコルを話すと想定します。これは、メッセージ長が異なることを意味します。
DMAを使用するときにのみ出てくるいくつかの質問は次のとおりです。
とにかく、ただ考えるための食べ物。
(私が思い出すように)受信側では、DMAは文字の一致またはターミナルカウントで終了します。一部のプロトコルと多くの対話型アプリケーションはこのモデルに簡単に適合せず、実際にキャラクターごとに処理する必要があります。また、通信リンクが信頼できない場合、DMAテクニックは不安定になる可能性があり、ストリーム内の1つの文字を失うと、DMAステートマシンを簡単に混乱させる可能性があります。
いくつかのプロジェクトでSTM32CubeMx / HALを使用していて、それが生成するUART処理ソフトウェアには受信側に明確な欠点があることがわかりました。
送信時には、通常、データブロックまたはテキスト行を送信します。この場合、データ転送の長さを前もって知っているので、DMAを使用することは明らかな解決策です。転送が完了すると割り込みが発生し、UART TX完了コールバック関数を使用して、送信が完了したことをメインコードに示し、別のデータブロックを送信できます。
データ受信に関しては、STが提供する機能はすべて、送信デバイスが送信を開始する前に送信する文字数を知っていることを前提としています。通常、これは不明です。割り込み機能は、受信したデータをバッファに格納し、事前定義された数の文字を受信したときに使用可能なデータがあることのみを示します。DMAまたは割り込み機能を使用して、順次単一文字転送をセットアップすることによりデータを受信しようとすると、これらのそれぞれのセットアップ時間は、最も遅いデータレート(ボーレート)以外で文字を失うことを意味します。データが失われ始めると、プロセッサーのクロック速度に依存します)、プロセッサーに過度の負荷がかかり、他の処理のための命令サイクルがなくなります
これを回避するために、小さなローカルサーキュラーバッファーにデータを格納し、メインコード(RTOSカウントセマフォ)によって読み取られるカウントを設定する独自の割り込みハンドラー関数を記述して、受信データの準備ができていることを示します。その後、メインコードはこのバッファからデータを自由に収集できます。データが収集される前にローカルバッファがオーバーフローしない限り、データの収集に遅延があっても問題ありません。