MMU

来源:互联网 发布:linux同名文件夹 编辑:程序博客网 时间:2024/06/01 09:58

MMU : 内存管理单元(硬件)

是一个协处理器


功能:

1:将虚拟地址转换成实际的物理地址
2:对物理内存设置访问权限

段模式映射:

物理地址与虚拟地址:

应用程序只能访问虚机地址,必须通过内核,这是MMU设定的


物理地址 = 基地址 + 偏移量
虚拟地址 = 基地址 + 偏移量


例:
虚拟地址:0x30000012 --> 高12位0x300 = 768(虚拟地址的基地址,描述符的索引号) --> 描述符表 --> 描述符(物理地址的基地址)
高12位为基地址,低20位为偏移量
0x30000012 = 0x300_00000 + 0x00000012
物理地址的偏移量跟虚拟地址的偏移量相同

描述符表:(存在于内存中),描述符表可以看成一个数组,该描述符表(数组)的首地址存在于MMU的c2寄存器里,CPU会找到描述符表中的描述符,然后判断后两位是不是10.如果是10.那么CPU会认为是段模式映射,MMU有C1--C10个寄存器,常用的是C1,C2,C3

C1:第0位,设置成1,是使能MMU; 设置成0,关闭MMU
C2: CPU主动去读C2,读出的是什么值,他就认为描述符表就在这个位置
C3: 设置权限检查,全1,允许任何应用程序访问

数据传输:

ARM向MMU传输数据:

MCR P15,0,R1,C1,C0,0
P15  :指定的协处理器
0  : 特定的值
R1,C1 把ARM中的R1寄存器里的值赋给C1处理器
C0  :第二个协处理器,P15没有第二个协处理器,指定为C0
0  :可选的协处理器操作码,P15没有,指定为0

MMU向ARM传输数据:

MRC P15,0,R2,C2,C0,0


示例项目:

有int *va = 0x76500000, int *pa = 0xfff00000, 设 *va = 123; 通过内存映射,使得打印*pa的内容也为123.

环境:tiny4412裸机mkdir mmu,创建mmu目录,在mmu目录下创建文件Makefile,main.c跟start.s,mkdir include,创建include目录,在该目录下创建文件stdio.h跟drive.h

代码如下:

start.s:

   .section .text   .global _start_start: stmfd sp!,{lr} bl main ldmfd sp!,{pc}

main.c:

#include #include <.h>int main(){unsigned long* va=(void*)(0xfff00000);   //  unsigned long* pa=(void*)(0x76500000);   // 0x4000_0000  --------  0x8000_0000*pa=123; mmu_init();  //初始化mmu_enable();  // 使能mmap();   // 映射   va---->pa   printf("%d\n",*va);   // 123printf("%d\n",*pa);   //123 }
stdio.h:
#ifndef _COMMON_H#define _COMMON_H#define  printf(...)    ( ( (int (*) (const char *format, ...)) 0x43e11a2c ) ( __VA_ARGS__ ))    #endif
drive.h:
#include void mem_init(unsigned long *ttb)      //一一映射{unsigned long pa;for(pa=0x00000000;pa<0x14000000;pa+=0x100000)//外设{ttb[pa>>20]=(pa&0xfff00000)|2; // 1 0 CPU找到描述表中的描述符,然后判断后两位}   //如果后两位是1 0 ,那么cpu认为是段模式映射for(pa=0x40000000;pa<0x80000000;pa+=0x100000)//用户可用地址{ttb[pa>>20]=(pa&0xfff00000)|2;}}void mmu_init(unsigned long *ttb){mem_init(ttb);__asm__ __volatile__( "mvn r0,#0x0\n""MCR p15,0,r0,c3,c0,0\n"//设置 c3:[0-31] 为1,允许任何访问"MCR p15,0,%0,c2,c0,0\n"//设置 c2 ,该寄存器的值为CPU自动读取后,分配在内存中的描述符表的收地址::"r"(ttb):"r0");}void mmu_enable(){__asm__ __volatile__("MRC p15,0,r0,c1,c0,0\n""orr r0,r0,#0x01\n"//设置 c1:[0] 使能MMU"MCR p15,0,r0,c1,c0,0\n":::"r0");}   mmap(ttb,0x76500000,0xfff00000)void mmap(unsigned long *ttb,unsigned long *va,unsigned long *pa){unsigned long v = (unsigned long)va;unsigned long p = (unsigned long)pa;ttb[p>>20]=(v&0xfff00000)|2;   //  ttb[0xfff]=0x76500000|2;}
Makefile:
all:arm-none-linux-gnueabi-gcc -fno-builtin -c main.c -o main.o -I ./include  arm-linux-as start.s -o start.oarm-none-linux-gnueabi-ld  -Ttext=50003000  start.o main.o   -o  armarm-none-linux-gnueabi-objcopy  -Ielf32-littlearm  -O binary arm  arm.binclean:rm -rf *.o  arm arm.bin







原创粉丝点击