1、MMU介绍

在uboot阶段并不是必须要开启MMU(内存管理单元),在没开启MMU前使用的是物理地址,开启MMU后使用的是虚拟地址。
MMU就是在物理内存和应用程序之间添加了一个层次,专门用来管理内存,这样写应用程序的人就不用关心物理内存的细节。
比如32位的机器理论上最大内存为4G,运行的程序以进程为单位,每个进程都认为自己拥有4G的内存,其实分配给该进程的物理内存肯定是没有4G的,进程的虚拟内存有4G。虚拟内存和物理内存都按照相同大小的划分页,虚拟内存的页和物理内存的页建立映射关系,当程序要访问的页不在内存时就会发生缺页异常,然后将磁盘里的页加载到内存中,如果此时物理内存没有空闲的页则还涉及页面置换。使用虚拟内存的好处:访问控制、内存分配和释放提供方便(比如malloc实际可能不是连续的)、运行超过物理内存大小的程序等。

2、虚拟地址和物理地址的转换

虚拟地址和物理地址的转换是依靠转换表,宏观上理解转换表:整个转换表可以看作是一个int类型的数组,数组中的一个元素就是一个表索引和表项的单元。数组中的元素值就是表项,这个元素的数组下标就是表索引。把虚拟地址按照一定规则进行查表,根据表的内容就可以知道对应的物理地址。映射分为段映射和页映射,这里是按照段映射(1M)进行讲解的,就是把内存按照1M为单位进行划分,4G的内存就分为4096个段,每个段对应一个页表项,每个页表项占4字节,页表总共占16KB。只需要构建好页表然后设置TTB,硬件会自动去查询页表进行转换。

3、开启MMU的步骤

(1)使能域访问,域访问是和MMU的访问控制有关的。
(2)构建虚拟地址转换表,并将转换表的基地址赋值到cp15协处理器的c2;
(3)使能MMU;

4、开启MMU的代码

 #if defined(CONFIG_ENABLE_MMU)enable_mmu:/* 使能域访问,将cp15的c3寄存器设置成0x0000ffff*/ldr  r5, =0x0000ffffmcr p15, 0, r5, c3, c0, 0       @load domain access register/* 设置转换表基地址,_mmu_table_base就是转换表的基地址*/ldr  r0, _mmu_table_baseldr  r1, =CFG_PHY_UBOOT_BASE    //CFG_PHY_UBOOT_BASE是uboot的链接地址ldr  r2, =0xfff00000bic r0, r0, r2  //将r0的bit20-bit31清零orr  r1, r0, r1  //将r0的值与r1进行或操作,并将结果保存在r1中mcr    p15, 0, r1, c2, c0, 0   //将r1的值写到cp15协处理器的c2寄存器中mmu_on:/* 开启MMU:cp15的c1寄存器的bit0控制MMU的开关。只要将这一个bit置1即可开启MMU。*/mrc p15, 0, r0, c1, c0, 0orr    r0, r0, #1mcr   p15, 0, r0, c1, c0, 0#endif#if defined(CONFIG_ENABLE_MMU)_mmu_table_base:.word mmu_table //mmu_table就是构建虚拟地址映射表#endif

5、构建虚拟映射表的代码

 /* form a first-level section entry */.macro FL_SECTION_ENTRY base,ap,d,c,b.word (\base << 20) | (\ap << 10) | \(\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1).endm.section .mmudata, "a".align 14// the following alignment creates the mmu table at address 0x4000..globl mmu_tablemmu_table:.set __base,0// Access for iRAM.rept 0x100FL_SECTION_ENTRY __base,3,0,0,0.set __base,__base+1.endr// Not Allowed.rept 0x200 - 0x100.word 0x00000000.endr.set __base,0x200// should be accessed.rept 0x600 - 0x200FL_SECTION_ENTRY __base,3,0,1,1.set __base,__base+1.endr.rept 0x800 - 0x600.word 0x00000000.endr.set __base,0x800// should be accessed.rept 0xb00 - 0x800FL_SECTION_ENTRY __base,3,0,0,0.set __base,__base+1.endr.set __base,0xB00.rept 0xc00 - 0xb00FL_SECTION_ENTRY __base,3,0,0,0.set __base,__base+1.endr.set __base,0x300.rept 0xD00 - 0xC00FL_SECTION_ENTRY __base,3,0,1,1.set __base,__base+1.endr.set __base,0xD00.rept 0x1000 - 0xD00FL_SECTION_ENTRY __base,3,0,0,0.set __base,__base+1.endr

构建页表就是通过多个循环,构建满足特定规则的int型数,因为一个页表项就刚好是4个字节,页表的每个位都有特定含义。
(1)FL_SECTION_ENTRY:这个宏就是用来构建页表项的,具体含义参考一级页表的页表项含义,实际效果就是定义一个特定的word类型数;
(2).rept和.end构成循环语句,比如.rept 0xD00 - 0xC00和.endr,就是循环(0xD00-0xC00)次。

6、一级页表的页表项含义

(1)段基址: 在设计地址映射时,从20bit开始的目的是要映射的物理地址要 1MB 对齐,段基址就是这段1MB 物理地址起始地址的高[31:20]位,每个条目中的描述符的段基址都不一样(以段来说,相差 1MB)。
(2) AP: AP 是用来设置权限的,与 C1 的 R/S 位结合使用。
(3) Domain 域: 不管是段模式还是页模式,系统都把 4GB 空间分为 16 个域,每个域有相同的权限检查(在 C3 设置 ),这里的 Domain 是用来标识本段所在的域
(4) C/B: C/B 位是控制位,与本条目(描述符)所在域的 Cache 和 Buffer 有关(是否允许本域开启 Cache 和 Buffer)
(5) [1:0]=0b10: 表示本描述符是表示段模式(段描述符标识)

7、最终得到的虚拟地址映射表

转换得到的虚拟地址映射表:VA                   PA                  length0-10000000            0-10000000          256MB10000000-20000000  0                   256MB20000000-60000000  20000000-60000000   1GB     512-1.5G60000000-80000000   0                   512MB   1.5G-2G80000000-b0000000    80000000-b0000000   768MB   2G-2.75Gb0000000-c0000000   b0000000-c0000000   256MB   2.75G-3Gc0000000-d0000000   30000000-40000000   256MB   3G-3.25Gd-完             d-完             768MB   3.25G-4G

嵌入式开发(S5PV210)——u-boot中开启MMU相关推荐

  1. 嵌入式开发:嵌入式应用程序中的信任链简介

    在设计嵌入式系统时,考虑安全性已经成为许多行业的需要.将设备连接到互联网的驱动器允许对系统进行远程攻击.想要构建安全嵌入式系统的嵌入式开发人员必须确保他们的设备实现信任链.在这篇文章中,我们将探讨什么 ...

  2. java restful接口开发实例_Spring Boot 中 10 行代码构建 RESTful 风格应用!

    点击上方"Java后端技术",选择"置顶或者星标" 你关注的就是我关心的! 作者:江南一点雨 微信公众号:牧码小子(ID:a_javaboy) 推荐阅读:10个 ...

  3. restful接口开发实例_Spring Boot 中 10 行代码构建 RESTful 风格应用

    松哥原创的四套视频教程已经全部杀青,感兴趣的小伙伴戳这里-->Spring Boot+Vue+微人事视频教程 RESTful ,到现在相信已经没人不知道这个东西了吧!关于 RESTful 的概念 ...

  4. 嵌入式开发板老化过程中显示温度与负载的关系脚本的用法

    有一次测试过程需要查看开发板在增加负载的过程是否正常,由于在增加负载的过程中打印温度,打印温度可以通过脚本直接体现出来,负载也可以使用top命令打印出来,但是top命令用于保存脚本就比较费劲了,如何将 ...

  5. 嵌入式开发(S5PV210)——u-boot的头文件包含问题

    前言 uboot和kernel的头文件包含比一般的程序更复杂,将头文件的路径用链接来表示,这样的用意是为了程序的可移植性.uboot是高度可移植的,不同的配置和编译指令可以编译出不同Soc和开发板的程 ...

  6. Spring Boot中的缓存支持(一)注解配置与EhCache使用

    随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...

  7. 嵌入式开发:使用条件复杂度测试嵌入式软件

    工程师们似乎在嵌入式软件开发的一个领域就是测试.工程师经常对设计和实现阶段感到兴奋,但是当涉及到证明系统工作时,努力和/或兴趣真的开始减弱.考虑到可能需要的时间和精力,这是完全可以理解的.嵌入式开发工 ...

  8. 【嵌入式开发】向开发板中烧写Linux系统-型号S3C6410

    作者 : 万境绝尘 转载请著名出处 终于拿到板子了, 嵌入式开发正式开启. 板子型号 : 三星 S3C6410 基于ARM11, 指令集基于arm6指令集; 为毛不是 Cortext A9的板子; 烧 ...

  9. 烧写linux系统到开发板中,【嵌入式开发】向开发板中烧写Linux系统

    作者 : 万境绝尘 终于拿到板子了, 嵌入式开发正式开启. 板子型号 : 三星 S3C6410 基于ARM11, 指令集基于arm6指令集; 为毛不是 Cortext A9的板子; 烧写内容 : Bo ...

最新文章

  1. 漫画:什么是“低代码”开发平台?
  2. 回调函数自定义传参_10分钟教你手写8个常用的自定义hooks
  3. VScode像Codeblocks一样,不启动调试和Debug直接运行
  4. java中的pane,Java中scroll pane的使用(一)– 动态改变其client的大小 | 学步园
  5. qml: 多级窗口visible现象;
  6. MySql事务及ACID实现的原理
  7. 网件rax40可以刷梅林_深度爆料网件RAX40评价如何?怎么样呢?真实体验曝光
  8. 细粒度情感分析在到餐场景中的应用
  9. quartus利用锁相环产生时钟_一种快速位同步时钟提取方案及实现
  10. 计算机系统盘怎么扩充,怎么给win7电脑C盘扩容
  11. 抽奖活动的奖品怎么设置?
  12. 爬虫小项目之爬取赛尔号
  13. meda中的一些小事项
  14. incsgo 可直接立刻取回皮肤的CSGO饰品皮肤开箱网站
  15. C语言_关于文件内容删除的两个方法总结
  16. 为什么角膜塑形镜的价格比隐形眼镜贵这么多?
  17. radius系列:freeradius测试
  18. OKR和KPI的区别
  19. What will matter?
  20. 如何提高公司员工执行力PPT?

热门文章

  1. 类间样本数量不平衡对分类模型性能的影响问题
  2. 如何搭建团队知识库?试试这款开源项目
  3. 荣耀6 Plus执行adb dumpsys中正在运行的service带有解释说明
  4. Redis原理及实践之GeoHash
  5. Redis原理剖析视频
  6. 【Tensorflow生成minist手写图像以及解决遇到的问题】
  7. 局域网的tomcat服务器找不到,解决:Tomcat 局域网IP地址 访问不了
  8. 调频广播立体声采集数据解调(含matlab源代码)
  9. 手机服务器物品不掉落,[娱乐|其他]InventoryKeeper —— 死亡护符|消耗物品来开启死亡不掉落吧[1.7.10-1.17]...
  10. 【泛微OA】JS限制明细行重复