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

下面将详细叙述MMU的设置,也是本人花费时间最多的一部分内容,无论是24106410甚至是Cortex-A8核的ARMMMU的设置基本都一样,所以移植时这部分可以直接搬过来,只需要更改全局内存映射表的映射关系即可。
先说说为什么在 EBoot 要设置 MMU ?其实有大牛们讨论过这个话题,在系统启动时会对页表进行重新映射,包括二级页表的设置,而在 EBoot 中只进行了一级页表的设置,最后也没有给出明确的答案,有的说是 WinCE 规定的,这里先不追究了,等以后研究了系统启动后的代码,再来讨论这个问题。 OAL 作为 WinCE 的开始需要启用虚拟内存,需要为 MMU 设置正确的页表进行地址映射,另外 WinCE 编译系统产生的二进制文件 .bib 使用的内存地址都是虚拟地址,这些虚拟地址是编译系统对二进制代码进行地址重定位的重要依据,所以在 Eboot 中对 MMU 进行设置,定义内存映射表的依据是全局内存映射表,在 PLATFORM\SMDK6410\SRC\INC\oemaddrtab_cfg.inc 文件中定义,内容如下:
g_oalAddressTable 

        ; mDDR 128 MB 
                ;DCD         0x80000000, 0x50000000,    64         ; 64 MB DRAM 
                [ SMDK6410_X5D 
                DCD         0x80000000, 0x60000000,     64         ; 64 MB DRAM 
                | 
                DCD         0x80000000, 0x50000000,    128         ; 128 MB DRAM 
                ] 

                DCD         0x90000000, 0x70000000,    4            ; SROM SFR 
                DCD         0x00000000, 0x00000000,    0            ; end of table
    它是以 g_oalAddressTable 宏开始的, DCD 用来分配一片连续的字存储单元,第一个参数是虚拟地址值,第二个参数是对应的物理地址值,第三个参数指明分配的大小,在映射表的最后,将三个参数的值均设为 0 ,表示是映射表的结束。下面看 startup.s 文件中的源码。
;------------------------------------ 
;         Initialize MMU Table 
;------------------------------------ 

        ;---------------------------- 
        ; Compute physical address of the OEMAddressTable. 

20 
                add                    r11, pc, #g_oalAddressTable -(. + 8) 
                ldr                    r10, =PT_1ST_BASE                                        ; (r10) = 1st level page table
   上面的代码将 R11 赋值为内存映射表的地址, R10 赋值为页表存储的地址, PT_1ST_BASE 在最开始处已经进行了定义,是页表基地址 0x50010000 ,解释一下 R11 的赋值语句。 ARM 处理器是流水线结构,允许指令预取,所以 PC 一般等于当前执行指令下面的第 2 条指令的地址,即 PC= 当前指令地址值 +8 字节,而“ . ”代表的是当前指令的地址值, PC= . + 8 , 这样 R11 获得的是 g_oalAddressTable 的地址。那为什么不直接 mov  r11  #g_oalAddressTable 进行赋值呢?确实不能这样,这样可以编译通过,但是执行不通过,只能采用和 PC 的相对值来换算。
                add                    r10, r10, #0x2000                    ; (r10) = ptr to 1st PTE for "unmapped space"
    这一条代码,将 R10 的值增加了 0x2000 ,因为第 1 MMU 的入口是地址值的高 14 为(过滤掉低 18 位), g_oalAddressTable 中看出, DRAM 的起始虚拟地址为 0x80000000 ,而 0x80000000>>18=0x2000 ,正好是 0x80000000 地址对应的第 1 MMU 入口的偏移值,也就是说 R10 现在存储的是 0x80000000 虚拟地址对应的页表的存储地址。那么为什么要右移 18 位?第 1 级页表将 4GB 的地址空间划分为多个 1MB 的段,对应的就有 4096 个页表项,而 ARM 地址映射时,虚拟地址被分为两部分:高位 + 低位,高位用来表示虚拟地址对应的页表针对页表首地址的偏移值,而低位表示在页表 1MB 地址空间中的偏移量,页表中的一个页表项可以描述 4 字节的虚拟页(因为 ARM 32 位的,每次都是读取 4 字节的数据),那么 1MB 的空间就需要 256KB 个这样的页表项才可以描述( 256K*4=1M ),而要表示 256KB 的大小,需要虚拟地址的低 18 位,剩下的高 14 位就可以用来计算虚拟地址对应页表相对于页表首地址的偏移量了。
                mov                    r0, #0x0E                             ; (r0) = PTE for 0: 1MB cachable bufferable 
                orr                    r0, r0, #0x400                    ; set kernel r/w permission
    上面的两条代码用来设置页表项的高速缓冲、写缓冲以及读写属性,具体的设置请参看 CP15 协处理器 C1 寄存器的功能,以后有时间会整理一篇关于 CP15 协处理器的说明。其实读者如果仔细看会发现,设置后 R0=0x40E ,和文件开始声明的 PT_1ST_ENTRY_CNB 变量的值是一样的,所以也可以用 mov  r0  PT_1ST_ENTRY_CNB 来代替两条语句,但是本人觉得用两条语句更能表明设置了什么,语义更明确。
25 
                mov                    r1, r11                                        ; (r1) = ptr to MemoryMap array 

30 
                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
    首先将 R11 也就是 g_oalAddressTable 指向的全局内存映射表的地址赋给 R1 (这就是高手的代码书写习惯,不会直接操作 R11 ),然后依次将 R1 指向的地址处的数据赋值给 R2 R3 R4 寄存器,“ #4 ”是表示每次操作完后, R1 的地址值增加 4 字节,指向下一个数据,其实对照 oemaddrtab_cfg.inc 的映射表,很容易发现, R2 获得的是虚拟地址的值, R3 获得的是对应物理地址的值, R4 则是这段存储空间的大小。
                cmp                    r4, #0                                        ; End of table? 
                beq                    %F40
    上面两条代码用来判断是否到了 oemaddrtab_cfg.in 中映射表的结尾,上面已经介绍过,映射表的最后一条的三个参数全部都为 0 ,标识映射表的结束。 beq 是一条跳转语句,表示如果相等,则跳转, %F40 表明向后寻找名称为 40 的标号( F=After )。

本文转自jazka 51CTO博客,原文链接:http://blog.51cto.com/jazka/572644,如需转载请自行联系原作者
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值