OK、これは私には本当に奇妙です。シミュレートされたCANバスドライバーがあります。これはLinuxカーネルモジュールです。次に、ファイル記述子を開いてメッセージを送信することでドライバーにアクセスするテストアプリケーションをユーザースペースで実行していioctl()
ます。
現在、CANバスドライバーは、x86プラットフォームで実行するために採用しているものです(組み込みのColdfireシステムで実行されていました)。組み込みシステムでは、メモリI / O領域にアクセスできるようにするためにrequest_mem_region()
/を使用する必要がありました。これを行う必要はありませんが、できるだけ多くのコードを共通に保ちたいと思います。ioremap()
ここにいくつかの有用な定義があります:
#define MCF_MBAR 0x10000000
extern unsigned int Base[];
extern unsigned int can_range[];
//This is the CAN registers on coldfire, just unused on my x86 desktop
Base[minor] = (MCF_MBAR + 0x1c0000);
can_range[minor] = 0x180;
次に、初期化中にこれを実行していました。
if(NULL == request_mem_region(Base[minor], can_range[minor], "CAN-IO")) {
return -EBUSY;
}
can_base[minor] = ioremap(Base[minor], can_range[minor]);
これを正しく理解していれば...ここで行っているのは、割り当てられていないメモリアドレスの範囲の予約を要求し、成功した場合は、それらにアクセスできるようにすることだけです。
現在マップされているアドレスを次の方法で確認しましたcat /proc/iomem
:
00000000-0000ffff : reserved
00010000-0009fbff : System RAM
0009fc00-0009ffff : reserved
000a0000-000bffff : Video RAM area
000c0000-000c8fff : Video ROM
000e2000-000e6fff : Adapter ROM
000f0000-000fffff : reserved
000f0000-000fffff : System ROM
00100000-1ffeffff : System RAM
00200000-0071038b : Kernel code
0071038c-00ad8a7f : Kernel data
00b58000-00c52fff : Kernel bss
<-- 101C0000-101C0180 : This is where I'd be mapping memory
1fff0000-1fffffff : ACPI Tables
e0000000-e0ffffff : 0000:00:02.0
e0000000-e0bfffff : vesafb
f0000000-f001ffff : 0000:00:03.0
f0000000-f001ffff : e1000
f0400000-f07fffff : 0000:00:04.0
f0400000-f07fffff : vboxguest
f0800000-f0803fff : 0000:00:04.0
f0804000-f0804fff : 0000:00:06.0
f0804000-f0804fff : ohci_hcd
f0806000-f0807fff : 0000:00:0d.0
f0806000-f0807fff : ahci
fee00000-fee00fff : Local APIC
fffc0000-ffffffff : reserved
その記憶を使っているものは何もないように見えるので、ここでは大丈夫だと思います。カーネルモジュールを正常にロードし、テストプログラムを実行すると失敗し、再度実行すると機能します。新しくロードされた後に最初に実行するたびに、失敗します... 2回目、3回目、n回目、それは機能します:
mike@linux-4puc:~> ./a.out
Starting driver test
Error 'Device or resource busy' opening CAN device
mike@linux-4puc:~> ./a.out
Starting driver test
We opened successfully
これが私の非常に単純なユーザースペースプログラムの一部です:
int fd;
char* dev = "/dev/can0";
printf("Starting driver test\n");
if ((fd = open(dev, O_RDWR)) < 0) {
printf("Error '%s' opening CAN device", strerror(errno));
close(fd);
return -1;
}
なぜこれが起こっているのかについてのアイデアはありますか?ドライバーからコードを削除すると、request_mem_region()
すべてが機能するので、私は愚かなことをしているだけだと思います...しかし、なぜそれが失敗するのですか?