作者:wogoyixikexie@gliet
本来打算在《MMU相关指令学习(一)(主要是页表设置指令)》搞定MMU指令问题的,但是这个实在是太长太多,太复杂了,现在就新开一文,就地解决!——刚好是第一百篇原创,值得纪念。
————————————————————————————————
Assembly code
;
——在OAL的startup.s有如下:
;
add r0, pc, #g_oalAddressTable - (. + 8)
;
bl KernelStart
;
——以前真的没有仔细看过这些汇编,看过才能知道这个wince的流程到底是怎么回事。
;
这相当于一到OAL阶段就要重新初始化页表,MMU,cache使能控制等 其实是一级、二级页表都在这里设置的
;
在C:/WINCE500/PRIVATE/WINCEOS/COREOS/NK/KERNEL/ARM/armtrap.s有KernelStart,现在好好分析一下。
;
----------------------------------------------------------------------------------------
;
KernelStart - kernel main entry point
;
;
The OEM layer will setup any platform or CPU specific configuration that is
;
required for the kernel to have access to ROM and DRAM and jump here to start up
;
the system. Any processor specific cache or MMU initialization should be completed.
;
The MMU and caches should not enabled.
;
;
This routine will initialize the first-level page table based up the contents of
;
the MemoryMap array and enable the MMU and caches.
;
;
NOTE: Until the MMU is enabled, kernel symbolic addresses are not valid and must be
;
translated via the MemoryMap array to find the correct physical address.
;
;
Entry (r0) = pointer to MemoryMap array in physical memory
;
Exit returns if MemoryMap is invalid
;
-------------------------------------------------------------------------------
LEAF_ENTRY KernelStart
;
add r0, pc, #g_oalAddressTable - (. + 8)
mov
r11, r0
;
(r11) = &MemoryMap (save pointer)
;
figure out the virtual address of OEMAddressTable
mov
r1, r11
;
(r1) = &MemoryMap (2nd argument to VaFromPa)
bl VaFromPa
mov
r6, r0
;
(r6) = VA of MemoryMap
;
convert base of PTs to Physical address
ldr r4, =PTs
;
(r4) = virtual address of FirstPT
mov
r0, r4
;
(r0) = virtual address of FirstPT
mov
r1, r11
;
(r1) = &MemoryMap (2nd argument to PaFromVa)
bl PaFromVa
mov
r10, r0
;
(r10) = ptr to FirstPT (physical)
;
Zero out page tables & kernel data page
mov
r0, #
0
;
(r0-r3) = 0's to store
mov
r1, #
0
mov
r2, #
0
mov
r3, #
0
mov
r4, r10
;
(r4) = first address to clear
add
r5, r10, #KDEnd-PTs
;
(r5) = last address + 1
18
stmia r4!, {r0-r3}
stmia r4!, {r0-r3}
cmp
r4, r5
blo %B18
;
Setup 2nd level page table to map the high memory area which contains the
;
first level page table, 2nd level page tables, kernel data page, etc.
add
r4, r10, #HighPT-PTs
;
(r4) = ptr to high page table
orr r0, r10, #0x051
;
(r0) = PTE for 64K, kr/w kr/w r/o r/o page, uncached unbuffered
str
r0, [r4, #0xD0*
4
]
;
store the entry into 8 consecutive slots
str
r0, [r4, #0xD1*
4
]
str
r0, [r4, #0xD2*
4
]
str
r0, [r4, #0xD3*
4
]
add
r8, r10, #ExceptionVectors-PTs
;
(r8) = ptr to vector page
bl OEMARMCacheMode
;
places C and B bit values in r0 as set by OEM
mov
r2, r0
orr r0, r8, #0x002
;
construct the PTE
orr r0, r0, r2
str
r0, [r4, #0xF0*
4
]
;
store entry for exception vectors
orr r0, r0, #0x500
;
(r0) = PTE for 4k r/o r/o kr/w kr/w C+B page
str
r0, [r4, #0xF4*
4
]
;
store entry for abort stack
str
r0, [r4, #0xF6*
4
]
;
store entry for FIQ stack (access permissions overlap for abort and FIQ stacks, same 1k)
orr r0, r8, #0x042
orr r0, r0, r2
;
(r0)= PTE for 4K r/o kr/w r/o r/o (C+B as set by OEM)
str
r0, [r4, #0xF2*
4
]
;
store entry for interrupt stack
add
r9, r10, #KPage-PTs
;
(r9) = ptr to kdata page
orr r0, r9, #0x002
orr r0, r0, r2
;
(r0)=PTE for 4K (C+B as set by OEM)
orr r0, r0, #0x250
;
(r0) = set perms kr/w kr/w kr/w+ur/o r/o
str
r0, [r4, #0xFC*
4
]
;
store entry for kernel data page
orr r0, r4, #0x001
;
(r0) = 1st level PTE for high memory section
add
r1, r10, #0x4000
str
r0, [r1, #-
4
]
;
store PTE in last slot of 1st level table
IF {FALSE}
mov
r0, r4
mov
r1, #
256
;
dump 256 words
CALL
WriteHex
ENDIF
;
Fill in first level page table entries to create "un-mapped" regions
;
from the contents of the MemoryMap array.
;
;
(r9) = ptr to KData page
;
(r10) = ptr to 1st level page table
;
(r11) = ptr to MemoryMap array
add
r10, r10, #0x2000
;
(r10) = ptr to 1st PTE for "unmapped space"
mov
r7, #
2
;
(r7) = pass counter
mov
r0, #0x02
orr r0, r0, r2
;
(r0)=PTE for 0: 1MB (C+B as set by OEM)
orr r0, r0, #0x400
;
set kernel r/w permission
20
mov
r1, r11
;
(r1) = ptr to MemoryMap array
25
ldr r2, [r1], #
4
;
(r2) = virtual address to map Bank at
ldr r3, [r1], #
4
;
(r3) = physical address to map from
ldr r4, [r1], #
4
;
(r4) = num MB to map
cmp
r4, #
0
;
End of table?
beq %F29
ldr r5, =0x1FF00000
and
r2, r2, r5
;
VA needs 512MB, 1MB aligned.
ldr r5, =0xFFF00000
and
r3, r3, r5
;
PA needs 4GB, 1MB aligned.
add
r2, r10, r2, LSR #
18
add
r0, r0, r3
;
(r0) = PTE for next physical page
28
str
r0, [r2], #
4
add
r0, r0, #0x00100000
;
(r0) = PTE for next physical page
sub
r4, r4, #
1
;
Decrement number of MB left
cmp
r4, #
0
bne %B28
;
Map next MB
bic r0, r0, #0xF0000000
;
Clear Section Base Address Field
bic r0, r0, #0x0FF00000
;
Clear Section Base Address Field
b %B25
;
Get next element
29
bic r0, r0, #0x0C
;
clear cachable & bufferable bits in PTE
add
r10, r10, #0x0800
;
(r10) = ptr to 1st PTE for "unmapped uncached space"
subs r7, r7, #
1
;
decrement pass counter
bne %B20
;
go setup PTEs for uncached space if we're not done
sub
r10, r10, #0x3000
;
(r10) = restore address of 1st level page table
IF {FALSE}
mov
r0, r10
mov
r1, #
4096
;
dump 4096 words
CALL
WriteHex
ENDIF
———————————————————————————————————————
上面的代码已经很多注释,已经非常明了了,我就不多废话了。
——————————
MMU,cache,TTB设置
——————————
现在,大体的方法明白了
——————————
一些重要的汇编宏定义
- MACRO
- mtc15 $cpureg, $cp15reg
- mcr p15,0,$cpureg,$cp15reg,c0,0
- MEND
- MACRO
- mfc15 $cpureg, $cp15reg
- mrc p15,0,$cpureg,$cp15reg,c0,0
- MEND
——————————————————————
-
Assembly code
-
;
The page tables and exception vectors are setup. Initialize the MMU and turn it on.
;
页表和异常向量表建立之后,初始化MMU并打开
mov
r1, #
1
mtc15 r1, c3
;
Setup access to domain 0 and clear other
;
domains including 15 for PSL calls (see above)
mtc15 r10, c2
;
;mtc15 是宏定义 把TTB(L1转换基地址放到C2)
mov
r0, #
0
mcr p15,
0
, r0, c8, c7,
0
;
Flush the I&D TLBs
mfc15 r1, c1
;
mfc15 宏定义 读出C1的值到r1
orr r1, r1, #0x007F
;
changed to read-mod-write for ARM920 Enable: MMU, Align, DCache, WriteBuffer
orr r1, r1, #0x3200
;
vector adjust, ICache, ROM protection
ldr r0, VirtualStart
;
这个很关键在代码中有 VirtualStart DCD VStart
cmp
r0, #
0
;
make sure no stall on "mov pc,r0" below
mtc15 r1, c1
;
enable the MMU & Caches
mov
pc, r0
;
& jump to new virtual address 跳到VStart运行
nop
总结:填写好二级页表,把二级页表的首地址存放到一级页表的表项最后最后;根据OEMAddresstable初始化L1页表;把L1的转换表的基地址放到协处理器的c1的寄存器。启动MMU等功能即可。
——现在基本没有什么疑问了,完成博客,今天晚上回去结贴。——目前对于一些domain、AP的设置等还是不是很明白。不过都是一个样,看看数据手册即可。阿门!大功告成。
如果还有疑问,请看CSDN论坛帖子: http://topic.csdn.net/u/20081231/10/bbde79c2-2884-48e3-9718-90d7fcc1afa8.html?seed=1947589160
这个讲的较详细。哈哈,最难的都理解了。我对ARM越来越有信心。
http://www.cnblogs.com/we-hjb/archive/2008/10/12/1309596.html
——这篇博客也讲得比较好,值得参考。
转载请标明:作者wogoyixikexie@gliet.桂林电子科技大学一系科协,原文地址:http://blog.csdn.net/gooogleman——如有错误,希望能够留言指出;如果你有更加好的方法,也请在博客后面留言,我会感激你的批评和分享。