嵌入式中 MMU的功能

简介:   学习嵌入式才发现要看的书太多,外面的世界很精彩啊,现在来说说MMU吧,MMU是Memory Management Unit的缩写,是用来管理虚拟内存系统的器件。 MMU通常是CPU的一部分,本身有少量存储空间存放从虚拟地址到物理地址的匹配表。

  学习嵌入式才发现要看的书太多,外面的世界很精彩啊,现在来说说MMU吧,MMU是Memory Management Unit的缩写,是用来管理虚拟内存系统的器件。 MMU通常是CPU的一部分,本身有少量存储空间存放从虚拟地址到物理地址的匹配表。此表称作TLB(转换旁置缓冲区)。所有数据请求都送往MMU,由 MMU决定数据是在RAM内还是在大容量存储器设备内。如果数据不在存储空间内,MMU将产生页面错误中断。在现代处理器中扮演着非常重要的角色。操作系统通过使用处理器的MMU功能,能够实现很多功能,具体如下:(MMU所起的作用也可参考http://wenku.baidu.com/view/09085f7427284b73f242502f.html

I. 虚拟内存。有了虚拟内存,可以在处理器上运行比实际物理内存大的应用程序。为了使用虚拟内存,操作系统通常要设置一个交换分区(通常是硬盘),通过将不活跃的内存中的数    据放入交换分区,操作系统可以腾出其空间来为其它的程序服务。虚拟内存是通过虚拟地址来实现的。

II. 内存保护。根据需要对特定的内存区块的访问进行保护,通过这一功能,我们可以将特定的内存块设置成只读、只写或是可同时读写。

  在嵌入式系统中,通常不会使用虚拟地址这一功能,因为它会使得任务的调度时间不具确定性。还有另一个原因就是,嵌入式系统的存储空间通常很小,有的只采用FLASH作为存储介质,并没有特定的空间用做交换分区。那在嵌入式系统中,MMU会用来做内存保护吗?是的,MMU在嵌入式系统中主要是用来做内存保护用的。还记得《程序中的段》中所提到的.text段和.rdata段吗?我们说这两个段通常是相邻放在连续的内存块中的,且这块内存会是只读的,而这就需要MMU来帮忙了!将这两个段所在的内存区块设置成只读的目的是,可以防止其内容被出错的程序意外的改写了。对于设置成只读的内存区当被意外的改写时,处理器会产生一个段异常,而操作系统则利用这一异常产生一个core(或dump)文件。通过这一文件,我们可以分析出是哪一段程序试图去改写只读内存的。应当说采用了内存保护的方法,可能使得程序出错时,我们找到问题的根源会相对的容易和快,因为其更接近出错的程序点。如果不具有内存保护功能,那么有可能程序去改写.text或.rdata段所在的区块时,还能运行,最后出错的地方可能离实际的出错点更为的“远”。

  那是谁来负责将.text和.rdata段设置成只读的呢?通常这可以在我们的应用程序在初始化操作系统时完成。

  对于MMU的一个特性我们在此不得不提及,MMU中存在页的概念,对于所有的MMU功能其操作都是以页的大小来进行的。比如,对于32位的x86处理器其页的大小是4K字节。在采用MMU设置内存的读写属性时,我们必须将页的起始地址作为设置参数,且这一地址必须是页的整数倍,k或者说地址必须是页对齐的。那从嵌入式系统开发的角度来看,我们需要注意什么呢?我们必须保护.text的起始地址必须是页对齐的,这是通过设置连接器的脚本来达到目的,即将.text段的起始地址设置成以页大小进行对齐,还有吗?先看图 1,为了解释方便我们假设.rdata段也在.text段中,且.text的起始地址已经采用连接器脚本设置成了页对齐的。


图 1
我们说了对于MMU的操作是以页来进行的,那我们得保证.text的大小是页的整数倍,那如何保证?很简单,将.data段的起始地址也通过连接器脚本设置成页对齐就行了。这样看来,为了使用MMU,可能会造成一点点的内存空间浪费,因为当.text的大小不是页的整数倍时,我们得将其变成页的整数倍,即实际的.text段与.data段可能会有空隙。图 2中示例了将.text段和.data段的起始地址设置成页对齐。

图 2

 在实践中,使用MMU解决了如下几个问题:
①使用DRAM作为大容量存储器时,如果DRAM的物理地址不连续,这将给程序的编写调试造成极大不便,而适当配置MMU可将其转换成虚拟地址连续的空间。
②ARM内核的中断向量表要求放在0地址,对于ROM在0地址的情况,无法调试中断服务程序,所以在调试阶段有必要将可读写的存储器空间映射到0地址。
③系统的某些地址段是不允许被访问的,否则会产生不可预料的后果,为了避免这类错误,可以通过MMU匹配表的设置将这些地址段设为用户不可存取类型。
   启动程序中生成的匹配表中包含地址映射,存储页大小(1M,64K,或4K)以及是否允许存取等信息。
例如:目标板上的16兆DRAM的物理地址区间为0xc000,0000~0xc07f,ffff;0xc100,0000~0xc17f,ffff;16兆ROM的虚拟地址区间为:0x0000,0000~0x00ff,ffff。          匹配表配置如下:
      可以看到左边是连续的虚拟地址空间,右边是不连续的物理地址空间,而且将DRAM映射到了0地址区间。 MMU通过虚拟地址和页面表位置信息,按照转换逻辑获得对应物理 地址,输出到地址总线上。


      应注意到的是使能MMU后,程序继续运行,但是对于程序员来说程序计数器的指针已经改变,指向了ROM所对应的虚拟地址。

相关文章
|
7月前
|
传感器 芯片
嵌入式微处理器片上外部
嵌入式微处理器片上外部
49 1
|
7月前
|
小程序 Linux 芯片
实用的嵌入式 C 程序!建议收藏
实用的嵌入式 C 程序!建议收藏
45 0
|
7月前
|
Linux API C语言
嵌入式
嵌入式
103 2
|
2月前
|
数据处理
基于ARM的嵌入式原理与应用:ALU的功能与特点
基于ARM的嵌入式原理与应用:ALU的功能与特点
125 0
|
存储 Java C#
day10嵌入式(2022.1.16)
day10嵌入式(2022.1.16)
|
传感器 设计模式 Ubuntu
嵌入式到底该怎么学
其实一直有人问我嵌入式怎么学,今天跟大家讲讲我的理解。因为嵌入式是一个泛的概念,可能很多人认为嵌入式就是嵌入式Linux。但是其实并不仅仅只有Linux, 像STM32,51单片机也属于这个范畴之内的,它们有的也可以跑协议栈,跑ucos等系统。所以其实嵌入式是有很多方向的,选择一个方向,做好,做精,都是有前途的。接下来,跟大家探讨一下嵌入式的一些方向,和如何去学习。我以前也是摸索着过来的,没人告诉我如何学习,也没有学习线路,所以走了很多弯路。所以希望这篇文章可以帮助到一些正在学习的人,当然这些内容可能有主观的东西,欢迎大家一起探讨吧。
嵌入式c++(八)
嵌入式c++(八)
嵌入式c++(八)