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,0P15 :指定的协处理器
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:
#includevoid 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
阅读全文
1 0
- MMU
- MMU
- MMU
- MMU
- MMU
- MMU
- MMU
- MMU
- MMU
- MMU
- mmu
- MMU
- MMU
- MMU
- MMU
- MMU
- MMU
- MMU
- 模仿微信九宫格图片展示控件
- leetcode-21-合并两个排好序的链表
- 折腾黑苹果走过的坑及一些解决方案
- DNS服务器1
- linux socket编程之多路复用select的例子
- MMU
- [Leetcode]_27 Remove Element
- 剑指offer
- swjtuoj 2380 Knapsack Problem
- Unity3D 学习笔记 —— Tween对象的实现与动作管理
- android 的单例模式
- c++第六次实验-数组的合并
- Unknown host 'android.oa.com'. You may need to adjust the proxy settings in Gradle.
- 用java编写一个计算器