像S3C64XX_GPACON 它本来的地址是0x7F008000 但是在内核 里它却把它用宏定义为
#define S3C_ADDR_BASE (0xF4000000)
#define S3C_ADDR(x) ((void __iomem __force *)S3C_ADDR_BASE + (x))
S3C_ADDR (0x00500000)
#define S3C64XX_VA_GPIO S3C_ADDR(0x00500000)
#define S3C64XX_GPA_BASE (S3C64XX_VA_GPIO + 0x0000)
这样的话用了虚地址先别说,但是有的却是直接用了它的真正的物理地址来进行操作
也就是直接iowrite() ioread()
这样也能准确操作到对应的寄存器,真是不可思议,这样的话地址不就是有点乱吗?
------解决方案--------------------
用户驱动中应该访问虚拟地址,内核将其翻译成物理地址;
两种情况下,使用的函数应该是不同的。
------解决方案--------------------
Linux系统不太了解。
WinCE也有物理地址和虚拟地址,情况和Linux应该是相同的。
在Boot的最初阶段使用物理地址,在MMU启动配置好页面之后,开始使用虚拟地址。
驱动里面通常是使用虚拟地址,不过有的时候也会有直接用物理地址的情况。
不管是直接操作物理地址,还是使用虚拟地址,经过MMU翻译成物理地址,
最终操作的寄存器等等都是相同的。
------解决方案--------------------
6410有进行虚拟地址和物理地址的转换,注意每个对内存的操作后面都会跟一个虚拟物理转换函数
------解决方案--------------------
MMU是硬件实现的虚拟地址和物理地址的转换,#define S3C_ADDR_BASE (0xF4000000)地址与0x7F008000的偏差是初始化时MMU将物理地址重映射的到的一个虚拟地址而0xF4000000应该是重映射后GPACON的虚拟地址,而linux内核中的虚拟地址到物理地址的转换是由软件实现的。
ARM架构内核空间中虚拟地址和物理地址仅存在一个偏移量,而用户空间是通过分页机制由页表和页表项实现虚拟地址和物理地址转换的,这两种转换都由内核代码实现。
iowrite() ioread() 给这两个函数实参,也是个虚拟地址而非物理地址,这个地址在使用前是需要映射的(ioremap)从而建立了虚拟地址和物理地址的联系。