本来打算在《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
如果还有疑问,请看CSDN论坛帖子: http://topic.csdn.net/u/20081231/10/bbde79c2-2884-48e3-9718-90d7fcc1afa8.html?seed=1947589160
总结:填写好二级页表,把二级页表的首地址存放到一级页表的表项最后最后;根据OEMAddresstable初始化L1页表;把L1的转换表的基地址放到协处理器的c1的寄存器。启动MMU等功能即可。
——现在基本没有什么疑问了,完成博客,今天晚上回去结贴。——目前对于一些domain、AP的设置等还是不是很明白。不过都是一个样,看看数据手册即可。阿门!大功告成。
这个讲的较详细。哈哈,最难的都理解了。我对ARM越来越有信心。
http://www.cnblogs.com/we-hjb/archive/2008/10/12/1309596.html
——这篇博客也讲得比较好,值得参考。
转载请标明:作者wogoyixikexie@gliet.桂林电子科技大学一系科协,原文地址:http://blog.csdn.net/gooogleman——如有错误,希望能够留言指出;如果你有更加好的方法,也请在博客后面留言,我会感激你的批评和分享。