本文将详细介绍MMU段式转换的过程,并在文末附上一篇讲MMU比较详细的文章。具体什么是MMU,什么时段是转换就不在本文讲了,直接戳文末的链接。
首先,进行段式转换的条件。我们要拥有一个虚拟地址,还有一级页表,这个一级页表一般是工程师在代码中建立起来的。每一个虚拟地址在这个一级页表中都有对应的表项。我们只需要知道一级页表的基地址,再将虚拟地址的高12位作为偏移,就可以找到该虚拟地址的表项了。从这里就可以看出,前12位相同的虚拟地址们在一级页表中其实都是共用同一个表项的。举个例子:0x56000000~0x560FFFFF这1MB的空间都是使用的同一个表项。
其次,我们找到了这个表项,那他有什么卵用呢?我们先看看表项的格式,如下图:
高12位为段的基地址,其他的位的意义参考《ARM920T_TRM1_S》的3.3.4小结,本文重点不在这里,故不再赘述。最重要的就是段的基地址,有了它,我们就能通过将它和虚拟地址的低20位进行拼接,从而得到我们外设需要的物理地址。这里也能看出来,一个段的大小有2^20也就是1MB这么大。
整个过程简而言之就是:通过虚拟地址的高12位找到一级页表中对应的表项,取该表项的高12位再与虚拟地址的低20位进行拼接,就得到了物理地址,这样就完成了从虚拟地址到物理地址的转换。
下面说说我在理解这些东西时候产生的误区,希望大家不要再犯:
1、之前一直误认为表项里面存储的就是物理地址,其实不是这样的,物理地址是将表项的高12位和虚拟地址的低20位进行拼接得来的。表项的低20位还是有别的用处的,比如决定一些权限位,以及是否使用cache,write_buffer等。
2、一级页表的基地址和段的基地址不是一回事,页表只是存储表项用的,表项记录了一些段的基地址。比如我们控制LED需要用0x56000010和0x56000014这两个地址处的寄存器,他们属于同一个段,段的基地址是0x56000000,而我们可能将页表存储在另外一个地方,比如0x30000000,所以这两个地址是毫无联系的。
参考代码:
//1、建立一级页表,这里把它放在内存的起始地址,也就是页表的基地址 //2、将虚拟地址的高12位作为偏移,用来寻找该虚拟地址对应的表项 //3、表项的内容:高12位为段的基地址的高12位,低20位为下述定义的宏 //4、物理地址:由段的基地址和虚拟地址的低20位拼接而来 #define GPBCON *((volatile unsigned long*)0xA0000010)
#define GPBDAT *((volatile unsigned long*)0xA0000014) #define MMU_SECTION (2 << 0)
#define MMU_CACHE (1 << 3)
#define MMU_BUFFER (1 << 2)
#define MMU_SPECIAL (1 << 4)
#define MMU_FULL_ACCESS (3 << 10)
#define MMU_DOMAIN (0 << 5) #define SECDESC MMU_SECTION | MMU_SPECIAL | MMU_DOMAIN | MMU_FULL_ACCESS
#define SECDESC_WB MMU_SECTION | MMU_SPECIAL | MMU_DOMAIN | MMU_FULL_ACCESS | MMU_BUFFER | MMU_CACHE void create_page_table()
{
//将一级页表放在内存起始地址
unsigned long *ttb = (unsigned long*)0x30000000; unsigned long vaddr, paddr; //虚拟地址
vaddr = 0xA0000000;
//物理地址
paddr = 0x56000000; //表项的地址 = 一级页表基地址 + 虚拟地址高12位(作为索引)
*(ttb + (vaddr >> )) = (0x56000000 & 0xfff00000) | SECDESC; //表项的内容 vaddr = 0x30000000;
paddr = 0x30000000; while(vaddr < 0x34000000)
{
*(ttb + (vaddr >> )) = (paddr & 0xfff00000) | SECDESC_WB;
vaddr += 0x100000; //0x100000 = 16^5 = 2^20 = 1MB
paddr += 0x100000; }
} void mmu_init()
{
__asm__(
"ldr r0, =0x30000000\n"
"mcr p15, 0, r0, c2, c0, 0\n" "mvn r0, #0\n"
"mrc p15, 0, r0, c3, c0, 0\n" "mrc p15, 0, r0, c1, c0, 0\n"
"orr r0, r0, #0x0001\n"
"mcr p15, 0, r0, c1, c0, 0\n"
:
: );
} //使用虚拟地址GPBCON, GPBDAT点亮LED int gboot_main()
{ //1、建立一级页表
create_page_table();
//2、写入TTB,打开MMU
mmu_init(); GPBCON = 0x15400;
GPBDAT = 0b11010111111; return ;
}
附加一篇讲MMU比较详细的文章(转):http://www.cnblogs.com/wrjvszq/p/4246634.html
如有错误或问题,欢迎指出,转载请注明出处。
18:09:45
2015-07-26
对MMU段式转换的理解的更多相关文章
-
ARM中MMU地址转换理解
首先,我们要分清ARM CPU上的三个地址:虚拟地址(VA,Virtual Address).变换后的虚拟地址(MVA,Modified Virtual Address).物理地址(PA,Physic ...
-
MMU段式映射(VA -> PA)过程分析
MMU:内存管理单元. CPU寻址的方式: 未使用MMU:CPU发出地址(PA) 直接内存寻址(SDRAM or DDRx). 使用MMU :CPU发出地址(VA) MMU接收CPU发来的地址 经过 ...
-
java基础类型数据与String类包装类之间的转换与理解
数据类型转换一般分为三种: 在java中整型,实型,字符型视为简单数据类型,这些数据类型由低到高分别为:(byte,short,char--int-long-float-double) 简单数据类型之 ...
-
FFmpeg(四) 像素转换相关函数理解
一.基本流程 1.sws_getCachedContext();//得到像素转换的上下文 2.sws_scale()://进行转换 二.函数说明 1.SwsContext *vctx = NULL; ...
-
JS 进制转换的理解
该事情的由来是来自于一个面试题,题目是这样的,[1,2,3].map(parseInt)的结果是什么? 作为菜鸟的我们一定是觉得分别把1,2,3分别交给parseInt,无非就是1,2,3嘛.其实结果 ...
-
【读书笔记::深入理解linux内核】内存寻址【转】
转自:http://www.cnblogs.com/likeyiyy/p/3837272.html 我对linux高端内存的错误理解都是从这篇文章得来的,这篇文章里讲的 物理地址 = 逻辑地址 – 0 ...
-
【读书笔记::深入理解linux内核】内存寻址
我对linux高端内存的错误理解都是从这篇文章得来的,这篇文章里讲的 物理地址 = 逻辑地址 – 0xC0000000:这是内核地址空间的地址转换关系. 这句话瞬间让我惊呆了,根据我的CPU的知识,开 ...
-
u-boot分析(十一)----MMU简单分析|u-boot分析大结局|学习规划
u-boot分析(十一) 通过前面十篇博文,我们已经完成了对BL1阶段的分析,通过这些分析相信我们对u-boot已经有了一个比较深入的认识,在BL2阶段大部分是对外设的初始化,并且有的我们已经分析过, ...
-
MMU功能解析、深入剖析、配置与使用
MMU = memory management unit 1.把虚拟地址转化成物理地址,防止地址冲突 2.访问权限管理 MMU把一个虚拟地址的20位到31位作为取出来,建立 一张表,叫做transla ...
随机推荐
-
Mac MySQL启动不了解决办法(MySQL卸载重新安装教程)
一段时间没用MySQL,今天使用时突然发现启动不了了,怎么点start都没用,或者输入密码了 还是没用... 好急...找了一圈资料,没发现特别好的解决办法,只能使用大招了----->< ...
-
JSON入门指南--服务端处理JSON
平时公司使用的ASP.NET MVC3来开发Web项目,其实在ASP.NET中已经原生的支持JSON.所以基本不需要引进Newtonsoft.Json.dll.下面看在MVC4中,后台生成JSON数据 ...
-
grunt不是内部或外部命令错误处理
如题, npm install -g grunt-cli发现grunt命令却不可用, 其实是环境变量问题,但是网上很多给出的方法其实是不准确的, 正确方法,可以通过npm root -g查看路径,之后 ...
-
Android studio的深坑 导jar包重复的异常处理
导包重复这个问题折磨了整整一天!! 第一个方法在gradle文件下看看有没有重复的包 如果有那么一切都是浮云分分钟搞定 ,最可恶的是在gradle里面没有. 在gradle里面找不到的话就要考虑一下 ...
-
浅析innodb_support_xa与innodb_flush_log_at_trx_commit
很久以前对innodb_support_xa存在一点误解,当初一直认为innodb_support_xa只控制外部xa事务,内部的xa事务是mysql内部进行控制,无法人为干预(这里说的内部xa事务主 ...
-
【学习笔记】分布式Tensorflow
目录 分布式原理 单机多卡 多机多卡(分布式) 分布式的架构 节点之间的关系 分布式的模式 数据并行 同步更新和异步更新 分布式API 分布式案例 Tensorflow的一个特色就是分布式计算.分布式 ...
-
第一节:EF Core简介和CodeFirst和DBFirst两种映射模式(以SQLite和SQLServer为例)
一. EF简介 1. 定义 Entity Framework (EF) Core 是轻量化.可扩展.开源和跨平台的数据访问技术,它还是一种对象关系映射器(ORM),它使.NET 开发人员能够使用面向对 ...
-
【转载】网站服务器运维记实:阿里云1核2G突发性能t5服务器突然变得卡顿
阿里云突发性能服务器1核2G的t5服务器在高资源利用率的情况下运行一段时间后,发现服务器反应变得很慢,通过windows远程桌面连接上服务器后查看到CPU性能一直在90%到100%之间,无法降下来.前 ...
-
MD5 两次加密
1.添加依赖 <dependency> <groupId>commons-codec</groupId> <artifactId>commons-cod ...
-
Error:Makefile:452: target &#39;config&#39; given more than once in the same rule
在解压的 linux2.6.15 文件夹下 make menuconfig 的时候出现下面的错误: Makefile:452: target 'config' given more than once ...