LoginSignup
16
17

More than 5 years have passed since last update.

LinuxのUIO(User space I/O) その2

Last updated at Posted at 2018-01-15

前回の続き

デバイスツリーを使わずにUIOを使用する方法

peri_pmcという名のレジスタを0x120a0000からの4KBをユーザー空間からアクセス可能にします。
その情報をセットしてuio_pdrv_genirqのドライバを登録するだけです。

そのコードの全体はgistに貼りました。ここ
要点は以下の部分です。
実質的にplatform_device_register()を呼びだすだけです。

static struct uio_info mydev_mem = {
    .name = "my_device",
    .version = "0.1",
    .irq = UIO_IRQ_NONE,
};

static struct resource uio_resources[] = {
    [0] = {
        .name   = "peri_pmc",
        .start  = 0x120a0000,
        .end    = 0x120a0fff,
        .flags  = IORESOURCE_MEM,
    },
    [1] = {
        .name   = "DUMMY",
        .flags  = IORESOURCE_IRQ,
    },
};

static struct platform_device my_dev = {
    .name = "uio_pdrv_genirq",
    .id = -1,
    .dev = {
        .platform_data = &mydev_mem,
    },
    .resource   = uio_resources,
    .num_resources  = ARRAY_SIZE(uio_resources),
};

static int __init uio_init(void)
{
    printk(KERN_INFO "uio_init\n");
    return platform_device_register(&my_dev);
}

実際に使用するときには、struct resourceの初期化のところだけを変更すればよいと思います。
このソースをビルドしてカーネルモジュールを作成し、それを insmodコマンドで登録すれば、/dev/uio0 のデバイスファイルが作成されます。
あとは前回の記事と同様です。

注意点

  • 割り込みを使用しない場合は、上記のようにstruct uio_info のirqにUIO_IRQ_NONEするとともに、struct resourceの方にもダミーのIORESOURCE_IRQのエントリが必要です。これが無いとinsmodしたときに、"failed to get IRQ" というメッセージでエラー終了してしまいます。

  • アクセス可能にするメモリ範囲の情報は struct uio_info ではなくて、struct resourceの方に書きます。

  • rmmodするとデバイスを削除することができますが、カーネルのログに"uio_pdrv_genirqのデバイスにreleaseの関数が実装されていない" という旨のエラーメッセージが出ます。

余談

私が最初にUIOを試してみたのは、数年前のカーネル3.0の頃でした。その当時はまだARMのデバイスドライバのデバイスツリー化が必須ではなかったので、この記事のカーネルモジュールの方式でやりました。
最近になって、またUIOを試してみようとしたのですが、当時のコードはもう紛失していて、かすかな記憶を頼りに思い出すのに苦労しました。やっぱりブログに書いておくのがいいですね。

UIOのカーネル内のドキュメント、The Userspace I/O HOWTOは最終更新が2006年12月になっていて、その後の更新が反映されていません。
このドキュメントによると、割り込みを使用せずにメモリのマッピングだけ行いたい場合には"uio_pdrv" というドライバを使用すればよいように書かれています。確かにカーネル3.0の当時はこのドライバは存在しました。
しかし、その後の変更で"uio_pdrv" は削除されてしまっています。おそらくは"uio_pdrv_genirq" でirq=UIO_IRQ_NONE にして使えばよいということだったのでしょう。
その後の変更の履歴は追えていませんが、ARMのデバイスツリーの対応が追加されています。
注意点のところにも書きましたが、uio_pdrv_genirqで割り込みを使用しない場合にはuioinfoのirqをUIO_IRQ_NONEにするだけでは足りなくて、struct resourceの方にもダミーのIORESOURCE_IRQのエントリが必要でした。とてもバグくさい挙動です。
UIO_IRQ_NONEの値は0なのですが、どうやらいろいろな人が建て増し的にコードを追加した結果、uio_infoのirqが0である場合に"割り込みは使用しない"という意味と"割り込みは未設定のため他の情報を参照せよ" の2つの意味がごちゃごちゃになってしまっているようです。
本来なら最新版カーネルでも同様の症状が出るかを確認して、バグをレポートしたいところですが、組み込みLinuxでは簡単に最新のカーネルを動かすことができないのがつらいところです。

16
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
17