MMU表示内存管理单元,负责虚拟内存映射到物理内存。
虚拟地址映射到物理地址的关键是构建映射表。MMU就是利用映射表格将虚拟地址转换成物理地址。虚拟地址在32系统中为4G,地址占4字节,如果映射表格中虚拟地址和物理地址是一一对应的关系,一条记录就占8字节,那么映射表就要32G.这明显是不合理的。
于是通过二级映射解决这个问题。地址共32位,把前12位作为基地址,后20位作为偏移量,将虚拟地址和物理地址作为的前12位一一对应,12位就是2的12次方为4k。 一条记录8字节,那么映射表格就只有32k,
下图左边为虚拟地址,右边为物理地址。比如有个虚拟地址为0x00123456,基地址为001 偏移量为23456.先通过映射表找到对于的物理地址为0x60100000,然后加上偏移量就是实际的地址0x60123456。
0x00100000 | 0x60100000 |
0x00200000 | 0x60200000 |
0x00300000 | 0x60300000 |
0x00400000 | 0x60400000 |
在tiny4412中,内存映射表更加的简单。把因为表格也是存放在内存中的,内存也有地址。那么就把内存利用起来。看下图:
0x70000000就表示映射表存储的位置,映射表格的内容就只有物理地址。虚拟地址就在表格的地址中体现。这样的话,内存映射表又缩减了一半,4G的虚拟地址只要16k的表格就能全部映射。
先看Tiny4412的内存表:
从表中可以知道0x30000000地址是没有内容的。现在要开启MMU,将0x30000000内存映射到0x50000000地址去,如果能够访问到0x3000000,就表示映射成功。代码如下:
1 int (*printf)(char *, ...) = 0xc3e114d8; 2 3 void init_ttb(unsigned long *ttb); 4 5 int main() 6 { 7 //0x32300000 -> 0x52300000; 8 unsigned long *pp = 0x52300000; 9 *pp = 0x22222222; 10 printf("*pp is %x\n", *pp); 11 //step 1: set mmu table 12 unsigned long ttb = 0x70000000; 13 init_ttb(ttb); 14 //step 2: enable mmu table 15 unsigned long mmu = 0; 16 mmu = 1 | (1 << 3) | (1 << 8); 17 __asm__ __volatile__(//开启mmu必须用汇编实现 18 "mov r0, #3\n" 19 "mcr p15, 0, r0, c3, c0, 0\n" //manager 20 "mcr p15, 0, %0, c2, c0, 0\n" //ttb address 21 "mcr p15, 0, %1, c1, c0, 0\n" //enable mmu 22 : 23 : "r" (ttb), "r" (mmu) 24 ); 25 26 unsigned long *pv = 0x32300000; 27 printf("*pv is %x\n", *pv); 28 } 29 30 void init_ttb(unsigned long *ttb) 31 { 32 unsigned long va = 0; 33 unsigned long pa = 0; 34 //0x00000000 ~0x14000000 -> 0x00000000 ~0x14000000 35 for(va=0x00000000; va<0x14000000; va+=0x100000){ 36 pa = va; 37 ttb[va >> 20] = pa | 2; 38 } 39 40 //0x40000000 ~0x80000000 -> 0x40000000 ~0x80000000 41 for(va=0x40000000; va<0x80000000; va+=0x100000){ 42 pa = va; 43 ttb[va >> 20] = pa | 2; 44 } 45 //0x30000000 ~0x40000000 -> 0x50000000 ~0x60000000 46 for(va=0x30000000; va<0x40000000; va+=0x100000){ 47 pa = va + 0x20000000; 48 ttb[va >> 20] = pa | 2; 49 } 50 }
可以访问0x32300000的内容,说明MMU开启成功。
下面是关于汇编代码中开启MMU的介绍。先是在ARM开发手册中查找关于MMU控制的相关信息,下图是MMU配置的内容
上面代码16行就是MMU的配置,将第一位置1表示 开启MMU,第三位置一表示开启写缓存。
未完待续。。。(等水平提升了在继续写,剩下的汇编代码实在看不懂)