OK,这是很奇怪我。 我有一个模拟的CAN总线驱动器,它是一个Linux内核模块。 然后我具有其中通过打开文件描述符和发送访问驱动程序用户空间中运行一个测试程序ioctl()
消息。
现在,CAN总线驱动只是我一直在采取新的x86平台上运行(这是我们的嵌入式的Coldfire系统上运行)。 在嵌入式系统它必须使用request_mem_region()
/ ioremap()
来获得I / O区访问,我并不需要这样做的记忆,但我想保持尽可能多的通用代码,我可以。
下面是一些有用的定义:
#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
它看起来像有什么期运用那段记忆,让我觉得我OK这里。 所以,我打开我的内核模块,成功,去跑我的测试程序,它失败,再次运行它和它的作品。 你运行它,它已经刚装入后每隔一日一次,它就会失败......第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()
从我的驱动程序代码一切正常,所以我觉得我只是在做一些愚蠢的事......但为什么它在它的方式失败?