您的位置:首页 > 其它

WinCE6.0学习之EBoot源码分析----startup.s(五)

2011-05-24 15:23 246 查看
; Comment:
; The following loop is to direct map RAM VA == PA. i.e.
; VA == 0x50XXXXXX => PA == 0x50XXXXXX for S3C6410
; Fill in 8 entries to have a direct mapping for DRAM

ldr r10, =PT_1ST_BASE ; Restore address of 1st level page table
ldr r0, =DRAM_BASE_PA_START
这部分开始建立虚拟地址到相等的物理地址的映射,因为是S3C6410,所以是0x50000000,如果是2410,则为0x30000000。首先将R10指向页表首地址(验证了前面那句减去0x30000000语句是没用的),R0存储的是0x50000000,既可以当做物理地址操作,也可以当做虚拟地址操作(因为是相等的地址映射)。

add r10, r10, #PTR_1ST_PTE ; (r10) = ptr to 1st PTE for 0x50000000
这条语句用来计算虚拟地址0x50000000对应的页表的存储地址,并赋值给R10。PTR_1ST_PTE在文件最开始处已经进行了定义,其实定义相当于将0x50000000>>18,用高14位计算相对于页表基地址的偏移量。

add r0, r0, #0x1E ; 1MB cachable bufferable
orr r0, r0, #0x400 ; set kernel r/w permission
mov r1, #0
; mov r3, #64 ; 64MB DRAM
mov r3, #128 ; 128MB DRAM
前两条语句用来设置页表对应页的缓冲读写属性,第四条语句,将DRAM的大小赋值给R3寄存器,该值的大小选择就是根据全局内存映射表中的DRAM设置的大小。该值不会大于512,因为WinCE最大支持512MB的物理内存。

45
mov r2, r1 ; (r2) = virtual address to map Bank at
cmp r2, #0x20000000:SHR:BANK_SHIFT
add r2, r10, r2, LSL #BANK_SHIFT-18
第一条和第二条语句要结合起来看,R2开始是0,cmp的比较就是为了保证DRAM的大小不超过512M,注释中的Bank大小就是1MB,BANK_SHIFT在最开始定义,大小为20,而0x20000000>>20=512。cmp指令影响的状态位,在后面的代码判断时使用。第三条语句其实还是计算对应的页表的存储地址的,LSL #BANK_SHIFT-18结合前面一条语句,相当于将R2>>18,这下就回到了前面介绍的,将高14位作为页表基地址的偏移量。

strlo r0, [r2]
add r0, r0, #0x00100000 ; (r0) = PTE for next physical page
subs r3, r3, #1
add r1, r1, #1
bgt %B45
第一条语句是将R0中的页表项写入R2指向的地址,但是没有str指令,而是strlo指令,因为这里有不同的地方,strlo实现的效果是,如果还没有超过512MB,那么像str指令一样,如果超过512MB,则不会往地址中写数据,忽略此次操作。个人认为,这样写的用意在于,当以后DRAM大小变化的时候,只需要该一个值,其他部分不变,而且如果设置的大于512MB,可以实现保护。第二条到第四条语句和前面介绍的部分类似。最后一条语句就是根据上面cmp的比较结果进行跳转的,bgt表示如果大于则跳转。

ldr r10, =PT_1ST_BASE ; (r10) = restore address of 1st level page table
该语句重新将R10指向页表基地址,因为下面会用到它。

; The page tables and exception vectors are setup.
; Initialize the MMU and turn it on.
mov r1, #1
mcr p15, 0, r1, c3, c0, 0 ; setup access to domain 0
mcr p15, 0, r10, c2, c0, 0
前面设置好页表以后,这里开始初始化MMU,并打开MMU。上面代码设置的是域0的访问控制属性,同时将页表的基地址存储到CP15协处理器的C2寄存器中。

mcr p15, 0, r0, c8, c7, 0 ; flush I+D TLBs
这条代码用来无效整个指令Cache、数据Cache和TLB,相当于清空所有MMU的相关空间。

mrc p15, 0, r1, c1, c0, 0
orr r1, r1, #0x0071 ; Enable MMU
orr r1, r1, #0x0004 ; Enable the Data Cache
第一条语句读取CP15的C1寄存器的数据到R1中,下面两条用来设置MMU的标志,使能MMU,使能数据Cache。

ldr r0, =VirtualStart

cmp r0, #0 ; make sure no stall on "mov pc,r0" below
mcr p15, 0, r1, c1, c0, 0
mov pc, r0 ; & jump to new virtual address
nop 首先R0存储标号VirtualStart的地址,它是一个虚拟地址,因为它出现在启用虚拟地址之后。确保标号VirtualStart的虚拟地址不为0,因为下面有mov pc r0,语句,不可以给pc赋值0。第三天语句将R1中的数据写入CP15的C1寄存器中,设置MMU标志,并启用MMU,最后通过直接给PC赋值,跳转到VirtualStart标号处。本文出自 “飞雪待剑” 博客,请务必保留此出处http://jazka.blog.51cto.com/809003/572649
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: