1

組み込み Linux デバイスへのレベル トリガー割り込みを使用する既存のシステムを移植しています。私は少し問題を抱えています。誰かが助けてくれることを願っています。私の計画は、poll() 関数 (ユーザー空間では、低レベルのドライバーの計画はありません) を使用して、gpio ラインが高くなったことを検出することでした。それは何かをするための兆候です。

残念ながら、その条件を有効にする方法がわかりません。現在、私は次のことを行っています。

  • gpio 番号を /sys/class/gpio/export に書き込みます
  • 方向を「中」に設定します
  • エッジを ? に設定します。

条件をクリアせずに poll() が複数回呼び出された場合でも、gpio ラインが高い場合は常にポーリングが返されるように GPIO を設定できますが、ラインが低い場合は待機しますか? poll() を使用する代わりに、何か他のものを使用する必要がありますか? ありがとう!

アップデート

私は解決策があると思ったが、明らかにそうではなかった。GPIO ラインのエッジを「立ち上がり」に設定しました。ハードウェア側では、この行はデータ バッファーの "FIFO 使用" カウントに関連付けられています。FIFO にデータがある場合、ラインはハイです。そうでなければ低いです。次に、次のシステムをセットアップします。

GetByte() {
    Is there data in the FIFO? {
        Read a byte.
        Return
    }
    Call poll() to wait for the data {
        Is there data in the FIFO? {
            Read a byte.
            Return
        }
    }
}

最初の「If」ステートメントが存在するのは、一度に 1 バイトしか読み取らず、poll() は、条件が変わらない場合はタイムアウトになる前に戻らないためです (また、複数のバイトが入っている場合はシステムに戻りません)。 FIFO)。私が今見ている問題は、poll() が返されることがありますが、FIFO にデータがないことです。実際、poll() は「1」を返しますが、FIFO は空であると報告します。

GPIO ラインの「立ち上がり」エッジ設定により、gpioXX/value ファイルが 0 から 1 に変更された場合にのみ、poll() が変更を検出することを期待しています。あれは正しいですか?これは poll() を使用する合理的な方法ですか、それとも別の設計を検討する必要がありますか?

4

2 に答える 2

1

やっと答えがわかった。FIFO を空にする前に GPIO の値ファイルを読み取って、次回 poll() が呼び出されたときに状態が良好であることを確認する必要があります。擬似コードの変更は次のとおりです。

GetByte() {
    Is there data in the FIFO? {
        Read the GPIO value file
        Read a byte.
        Return
    }
    Call poll() to wait for the data {
        Is there data in the FIFO? {
            Read a byte.
            Return
        }
    }
}

バイトが利用可能な場合は、常にバイトを読み取ろうとします。FIFO の最後のバイトの場合は、まず GPIO 値ファイルを読み取ります。これを行うと、レベル トリガー割り込みラインが高いことがわかっているので、poll() が確認する可能性のある保留中のファイル イベントを安全にクリアできます。今、私はバイトを読みました。

poll() を呼び出すと、割り込みからの立ち上がりエッジが検出されない限り返されないことがわかります。簡単な修正ですが、何をする必要があるかを完全に理解するまで、kernel/fs/sysfs/file.c のコメントを読むまではそうではありませんでした。

于 2012-10-16T14:34:07.503 に答える
0

ドライバーを書かないと、自分でハードウェア レジスタにアクセスする必要があるような気がします。これには、1. ハードウェアを理解して、アクセスする必要があるレジスターのハードウェア アドレスを把握する、2. open & mmap を使用してレジスターへのポインターを取得する、3. ポインターを逆参照する、などの作業が必要です。

私のプロジェクトから抜粋したコードを次に示します。

fd = open("/dev/mem", O_RDWR|O_SYNC);
if (fd == -1)
{
perror("open /dev/mem");
exit(1);
}
unsigned char *start;
start = (unsigned char*)mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED,
fd, 0x80810000);
于 2012-09-27T23:54:51.897 に答える