3

私たちのグループは、組み込みプロセッサ(Phytec LPC3180、ARM9)を使用しています。LPC3180のI2Cバスの1つに4つのMAX3107UARTチップを含むボードを設計しました。重要な場合は、このプロセッサで利用可能な最新バージョンであるカーネル2.6.10を実行しています(この製品のサポートはあまり良くありません。PhytecおよびPhytecが提供する多数のドライバを開発または修正する必要がありました。この製品のLinuxコード(特にカーネルバージョン)のアップグレードには関心がないようです。これは、LPC3180が優れたデバイスであるという点で、特にイーサネットを必要とせず、実際には必要としない低電力の組み込み製品のコンテキストでは、あまりにも悪いです。エーテルネットは必要ありません(イーサネットコントローラーチップの関連する電力消費のため)。

I2Cバス上の4つのデバイス(MAX3107 UARTチップ)の1つが文字を受信すると、割り込みを生成します。4つのMAX3107チップすべての割り込みラインは共有され(オープンドレインプルダウン)、ラインはレベル割り込み用に構成された3180のGPIOピンに接続されます。3017の1つが割り込みを生成すると、次の処理を(大まかに)実行するハンドラーが実行されます。

spin_lock_irqsave();
disable_irq_nosync(irqno);
irq_enabled = 0;
irq_received = 1;
spin_unlock_irqrestore()
set_queued_work();  // Queue up work for all four devices for every interrupt
                    // because at this point we don't know which of the four
                    // 3107's generated the interrupt
return IRQ_HANDLED;

上記のコードを終了する前に割り込みが再度有効にされないことに注意してください。これは私がやや厄介だと思うことです。むしろ、ドライバーは、(「enable_irq(LPC_IRQ_LINE)関数呼び出し」を使用して)下半分のワークキュータスクによって割り込みが再度有効になるように記述されています。ワークキュータスクは割り込みコンテキストで実行されないため、スリープする可能性があると思います。割り込みハンドラにとっては悪い考えだと私は信じています。

上記のアプローチの理論的根拠は次のとおりです。1。4つのMAX3107UARTチップの1つが文字を受信し、割り込みを生成する場合(たとえば)、割り込みハンドラは4つのI2Cデバイスのどれが実際に割り込みを引き起こしたかを把握する必要があります。ただし、明らかに、I2C読み取りはスリープする可能性があるため、上半分の割り込みハンドラーのコンテキスト内からI2Cデバイスを読み取ることはできません。これは、割り込みハンドラーの上半分には不適切と見なされます。2.上記の問題(つまり、どのデバイスが割り込みを引き起こしたか)に対処するために採用されたアプローチは、割り込みを無効のままにして上半分のハンドラーを終了することです。その後、非割り込みコンテキストコードはI2Cバス上の4つのデバイスのそれぞれにクエリを実行できます。どちらが文字を受信したか(したがって、割り込みを生成したか)を把握します。3.3。下半分のハンドラーが割り込みを生成したデバイスを特定すると、下半分のコードはそのチップの割り込みを無効にして、LPC3180への割り込みラインを再トリガーしないようにします。その後、シリアルデータを読み取って終了します。

ここでの主な問題は、割り込みハンドラの上半分から4つのMAX3107UARTチップをクエリする方法がないことです。上半分が戻る前に単に割り込みを再度有効にすると、同じチップが再び割り込みを生成し、上半分が割り込みを無効にし、下半分の作業キューをスケジュールして無効にする状況につながると思います割り込みは、下半分のコードがチップに到達して割り込みを発生させる前に、別の割り込みが発生したなどの理由で、同じ場所に戻るだけです。

このドライバーに対処するためのアドバイスをいただければ幸いです。ドライバーの上半分で割り込みを無効にして、上半分のドライブコードが存在する前に再度有効にしないという考えは本当に好きではありません。これは安全ではないようです。

ありがとう、

ジム

PS:私の読書では、上記の要件に対処する手段としてスレッド化された割り込みを発見しました(少なくとも、http://lwn.net/Articles/302043/などのWebサイトの記事の私の解釈です)。Phytecが提供する2.6.10カーネルにスレッド割り込み関数が含まれているかどうかはわかりません。今後数日でこれを調査するつもりです。

4

2 に答える 2

1

コードが適切に記述されていれば、前の割り込みの処理が完了する前にデバイスが割り込みを発行しても問題ありません。上半分でブロック操作を実行したくないのは正しいですが、ブロック操作は下半分、実際、それが彼らが存在する理由の一部です!

この場合、上半分が下半分だけをスケジュールし、下半分が 4 つのデバイスすべてをループして、保留中の要求を処理するアプローチをお勧めします。複数のデバイスで処理が必要な場合もあれば、何も必要ない場合もあります。

更新: 負荷テストでシステムに過負荷をかける可能性があることは事実です。重い負荷を処理するためにソフトウェアを最適化する必要がある場合があります。さらに、私はこれをテストするための 3180 と 4 つの 3107 (または同様のもの) を持っていないので、理論的に話していますが、割り込みを無効にする必要がある理由がまったくわかりません。

一般に、ハードウェア デバイスが割り込みをアサートすると、現在の割り込みがクリアされるまで別の割り込みはアサートされません。したがって、1 つの int 行を共有する 4 つのデバイスがあります。

  1. 上半分が発火し、ワーク キューに何かを追加します (つまり、下半分をトリガーします)。
  2. 下半分は、その int 行のすべてのデバイス (つまり、4 つの 3107 すべて) をスキャンします。
  3. それらの1つが割り込みを引き起こした場合、データを完全に処理するために必要なすべてのデータを読み取ります(おそらく、より高いレベルの処理のためにキューに入れますか?)
  4. 現在のデバイスの割り込みを「クリア」します。

割り込みをクリアすると、デバイスは別の割り込みをトリガーできますが、その前にはトリガーできません。

この特定のデバイスの詳細:

このデバイス (MAX3107) には 128 ワードのバッファがあり、デフォルトでは 1 ワードごとに中断されているようです。しかし、FIFO レベル レジスタを設定することで、バッファをより有効に活用できるはずです。次に、そのワード数が受信された後にのみ中断されます (または、送信速度を遅くする必要があるしきい値を超えて tx FIFO をいっぱいにした場合 (つまり、ソフトウェアでより多くのバッファリングを行う必要があります))。

基本的に、デバイスからデータを定期的に (おそらく 100 ミリ秒または 10 ミリ秒ごとに) プルし、しきい値を超えたという警告として割り込みを機能させるだけで、定期的な機能をスケジュールすることが考えられます。すぐに実行するか、呼び出される速度を上げます。

于 2012-11-26T10:29:05.337 に答える
1

エッジベースではなくレベルベースの割り込みを使用するため、割り込みは有効化および無効化されます。その影響は、Jim さんが持っているドライバー コード ヘッダーで明示的に説明されています。

レベルベースの割り込みは、1 つの UART に到着した直後に別の UART に到着した文字からのエッジ割り込みを失うことを避けるために必要でした。実際、これは、このドライバーの最初のエッジ割り込みバージョンで 1 つ以上の UART が実行されたときに発生したこととまったく同じです。

現在のスキームで失敗が観察されましたか?

よろしく、ドライバーの作者(他の人)

于 2012-11-30T21:14:41.930 に答える