写第一个基于ARM9的wince驱动的时候,参照人家的例子,加入这个函数,但是本质上的作用是什么我不清楚?看不明白~求教
- volatile IOPreg *s2440IOP = (IOPreg *)IOP_BASE;
- volatile INTreg *s2440INT = (INTreg *)INT_BASE;
- BOOL g_bInit;
- /*******************************************************************
- ** 函数: Virtual_Alloc
- ** 功能: 配置虚拟内存地址
- ********************************************************************/
- void Virtual_Alloc(void)
- {
- s2440IOP=(volatile IOPreg *)VirtualAlloc(0,sizeof(IOPreg),MEM_RESERVE,PAGE_NOACCESS);
- if (s2440IOP==NULL) //分配到的地址为空,即指向0地址
- {
- RETAILMSG(1,(TEXT("For s2440IOP: VirtualAlloc faiLED!\r\n")));//串口打印出错信息
- }
- else
- {
- if (!VirtualCopy((PVOID)s2440IOP,(PVOID)(IOP_BASE),sizeof(IOPreg),PAGE_EXECUTE_READWRITE|PAGE_NOCACHE))
- {
- RETAILMSG(1,(TEXT("For s2440IOP: VirtualCopy faiLED!\r\n")));//串口打印出错信息
- }
- }
- }
有什么问题么,这就是保留一段虚拟地址,然后映射到device的io memory。因为arm里一旦mmu开启,所有内存(包括io memory)访问都要用虚拟地址,所以这里必须建立一个映射,才能访问io。
楼上的理解有误。
MMU映射只需一张映射表,在.bib文件中配置的,MMU的虚拟地址就是操作系统的物理地址,内核态都可以直接访问的。
这里的虚拟地址是操作系统中的虚拟地址,用户态无法直接访问操作系统的物理地址,所以要做这个映射。
因为开了MMU,而WINCE 中的地址是虚拟地址,要访问物理地址的寄存器就必须开出一分内存来把虚拟地址映射到物理地址上,进而访问虚拟地址就能达到访问物理地址的寄存器的效果。
采用虚拟内存技术有以下三点好处:第一,可以根据用户的需要重新分配内存地址空间;第二,可以隔离硬件物理地址空间的变化对软件的影响;第三,可以对存储空间引入保护机制。
楼上说的我不是很明白,啥叫操作系统的物理地址和操作系统的虚拟地址,咱们可以讨论一下,我也学习学习。
我的理解是,总线上跑的就是物理地址,指令中用到的就是虚拟地址。虚拟地址4个g里,kernel space是上2个g,user space是下两个g。应用程序不能访问kernel space。这说的都是虚拟地址。mmu负责虚拟地址到物理地址的映射,是个2级(或者3级)的映射表。.bib(OEMAddressTable)文件定义了一级映射表的一部分,从ox80000000往上的2个512M,一个cachable,一个uncachable。这部分映射是静态的,在startup里实现,如果楼上把这部分叫做操作系统的物理地址,那我可以理解。我不理解的是VirtualCopy的第二个参数,IOP_BASE,这个参数可以是操作系统的物理地址,也可以是个总线上跑的物理地址,前者相当于同一个(总线)物理地址有两个不同的映射,后者的话需要在最后一个参数里加上PAGE_PHYSICAL。之所以允许后者,是因为有时候不能把所有io memory都映射到512M里,为此kernel space还保留了256M(0xd0000000-0xe0000000)来让个别驱动来做静态映射。
如果我理解的有错的话,希望指正。
cachable,uncachable都是虚拟的,物理地址就是物理地址,那有什么操作系统的物理地址
虚拟内存就是利用MMU硬件单元将CPU发出的虚拟内存地址根据用户自己依需要构造设置的页表而翻译成实际的物理地址,物理地址空间的安排分配通常取决于CPU和硬件电路的设计,不存在什么操作系统的物理地址
引用: 引用楼主 rejoice818 的回复:
写第一个基于ARM9的wince驱动的时候,参照人家的例子,加入这个函数,但是本质上的作用是什么我不清楚?看不明白~求教
C/C++ codevolatile IOPreg*s2440IOP= (IOPreg*)IOP_BASE;volatile INTreg*s2440INT= (INTreg*)INT_BASE;
/*能告诉我IOP_BASE和INT_BASE得值吗? 这个应该是在S2440.h或者s3c2440.h之类的头文件中有定义,而且如果我猜得不错的话,地址是在0xA0000000到0xc0000000之间的!---因为这是静态映射,之后你如果要配置寄存器的值,只要s2440IOP->rGPDCON=xx 如此就可以了
*/
BOOL g_bInit;/*******************************************************************
** 函数: Virtual_Alloc
** 功能: 配置虚拟内存地址
//而下面的就是动态映射了,如果上面所说的成立的话,下面的代码可以不要
********************************************************************/void Virtual_Alloc(void)
{
s2440IOP=(volatile IOPreg*)VirtualAlloc(0,sizeof(IOPreg),MEM_RESERVE,PAGE_NOACCESS);if (s2440IOP==NULL)//分配到的地址为空,即指向0地址 {
RETAILMSG(1,(TEXT("For s2440IOP: VirtualAlloc faiLED!\r\n")));//串口打印出错信息 }else
{if (!VirtualCopy((PVOID)s2440IOP,(PVOID)(IOP_BASE),sizeof(IOPreg),PAGE_EXECUTE_READWRITE|PAGE_NOCACHE))
{
RETAILMSG(1,(TEXT("For s2440IOP: VirtualCopy faiLED!\r\n")));//串口打印出错信息 }
}
}
9
物理地址 (physical address): 放在寻址总线上的地址。放在寻址总线上,如果是读,电路根据这个地址每位的值就将相应地址的物理内存中的数据放到数据总线中传输。如果是写,电路根据这个地址每位的值就将相应地址的物理内存中放入数据总线上的内容。物理内存是以字节(8位)为单位编址的。
虚拟地址 (virtual address): 4G虚拟地址空间中的地址,程序中使用的都是虚拟地址。
如果CPU寄存器中的分页标志位被设置,那么执行内存操作的机器指令时,CPU会自动根据页目录和页表中的信息,把虚拟地址转换成物理地址,完成该指令。