当前位置: 技术问答>linux和unix
不抱希望的问下几个驱动开发的问题?
来源: 互联网 发布时间:2015-12-11
本文导语: 1)phys_to_virt(),ioreamp(),iomap(linux2.6没有了),IO_ADDRESS(),这几个咚咚都是用来把物理地址转换成虚拟地址的,有什么区别呢? 同一个物理地址通过以上方法转换后的地址不一样,转换后的地址有的能不读写,有的不能读写...
1)phys_to_virt(),ioreamp(),iomap(linux2.6没有了),IO_ADDRESS(),这几个咚咚都是用来把物理地址转换成虚拟地址的,有什么区别呢?
同一个物理地址通过以上方法转换后的地址不一样,转换后的地址有的能不读写,有的不能读写。ARM下访问一个硬件里的寄存器(告诉了其物理地址0x00214000),该用哪个函数转化成虚拟地址后访问呢。
2)linux2.4下,devfs_register()用来注册一个设备,可以在/dev目录下看到注册的设备名,
然后通过 mount 就可以读取设备了。linux 2.6 没有了这个函数,只能mknod 在/dev建一个,可是mount 显示没有改设备,有没有其他的函数能取代devfs_register的功能。
3)中断号(如:12)在linux2.4用request_irq下能申请,在linux2.6下却申请不到,可能的原因有哪些呢?
4)怎样把io端口直接映射到linux内核空间?
linux2.4下通过以下方式可以把物理地址0x0020000开始的连续256k的空间映射到0xf0000000的虚拟空间;
static struct map_desc mx1ads_io_desc[] __initdata = {
{ IO_ADDRESS(0x0020000), 0x0020000, SZ_256K , DOMAIN_IO, 0, 1},
};
以上的IO_ADDRESS(X) 为( (x)|0xf0000000).
在linux2.6下:
static struct map_desc imx_io_desc[] __initdata = {
{
.virtual = IO_ADDRESS(0x0020000),//IO_ADDRESS(X) 为((x)|0xe0000000
.pfn = __phys_to_pfn(0x0020000),
.length = SZ_256K,
.type = MT_DEVICE
}
};
出现的问题是,
在linux2.4下printk("the regiest value=%0xn",((*volatile unsigned long*)0xf0200000));没有问题
在linux2.6下printk("the regiest value=%0xn",((*volatile unsigned long*)0xe0200000));出错。
难道上面的映射的有问题吗?
5)linux2.4下有request_dma(),free_dma(),enable_dma(),来操作DMA,在linux2.6确没有了这些函数,该怎样移植这些函数呢?
6)lwn.net上的driver-transport实在是不能解决上面的问题,有没有其他资料来源?
同一个物理地址通过以上方法转换后的地址不一样,转换后的地址有的能不读写,有的不能读写。ARM下访问一个硬件里的寄存器(告诉了其物理地址0x00214000),该用哪个函数转化成虚拟地址后访问呢。
2)linux2.4下,devfs_register()用来注册一个设备,可以在/dev目录下看到注册的设备名,
然后通过 mount 就可以读取设备了。linux 2.6 没有了这个函数,只能mknod 在/dev建一个,可是mount 显示没有改设备,有没有其他的函数能取代devfs_register的功能。
3)中断号(如:12)在linux2.4用request_irq下能申请,在linux2.6下却申请不到,可能的原因有哪些呢?
4)怎样把io端口直接映射到linux内核空间?
linux2.4下通过以下方式可以把物理地址0x0020000开始的连续256k的空间映射到0xf0000000的虚拟空间;
static struct map_desc mx1ads_io_desc[] __initdata = {
{ IO_ADDRESS(0x0020000), 0x0020000, SZ_256K , DOMAIN_IO, 0, 1},
};
以上的IO_ADDRESS(X) 为( (x)|0xf0000000).
在linux2.6下:
static struct map_desc imx_io_desc[] __initdata = {
{
.virtual = IO_ADDRESS(0x0020000),//IO_ADDRESS(X) 为((x)|0xe0000000
.pfn = __phys_to_pfn(0x0020000),
.length = SZ_256K,
.type = MT_DEVICE
}
};
出现的问题是,
在linux2.4下printk("the regiest value=%0xn",((*volatile unsigned long*)0xf0200000));没有问题
在linux2.6下printk("the regiest value=%0xn",((*volatile unsigned long*)0xe0200000));出错。
难道上面的映射的有问题吗?
5)linux2.4下有request_dma(),free_dma(),enable_dma(),来操作DMA,在linux2.6确没有了这些函数,该怎样移植这些函数呢?
6)lwn.net上的driver-transport实在是不能解决上面的问题,有没有其他资料来源?
|
phys_to_virt() 仅仅是内核来直接进行地址转换的,这个函数只是简单加减一个偏移量,比如一个确切的物理地址用来转换成内核可以识别的地址,如果0x00214000 是确切的物理地址,则应该用phys_to_virt,可以用__raw_readx __raw_writex 来访问试试
ioreamp() 会把物理地址映射到内核虚拟地址空间,可能会有页表操作,我觉得可以理解为纯粹的映射,要用readx writex 这样的存取操作
愚见遇见,纯属赚分 :)
ioreamp() 会把物理地址映射到内核虚拟地址空间,可能会有页表操作,我觉得可以理解为纯粹的映射,要用readx writex 这样的存取操作
愚见遇见,纯属赚分 :)
|
#define IMX_IO_PHYS 0x00200000
0x00214000 - IMX_IO_PHYS + 0xe0000000
0x00214000 - IMX_IO_PHYS + 0xe0000000
|
vaddr = phys_to_virt(0x00214000); __raw_readb(vaddr ) ; 试试啦
|
IO_ADDRESS(X) 为((x)|0xe0000000 你怎么断定IO地址偏移就是0xe0000000 呢?你的ARM 具体型号是什么的?0x00214000 在imx-arm 上倒是配置好了的
|
不抱希望的进来接几分
|
#define MMCSDR_BASE IO_ADDRESS(0x00214000) 方法二不行
#define MMCSDR_BASE __phys_to_virt(0x00214000)
我觉得LZ这样定义不是很好的,宏第二次执行时,很难保证映射到同一地址
#define MMCSDR_BASE __phys_to_virt(0x00214000)
我觉得LZ这样定义不是很好的,宏第二次执行时,很难保证映射到同一地址
|
真正的高手是为了解决问题而不是为了得分,除了分之外还有很多美好的东西。不要一味着看着分是多少?
|
3) 说明有别的设备占用了这interrupt line.
|
不抱希望的接分