历史上的今天
返回首页

历史上的今天

今天是:2025年02月09日(星期日)

正在发生

2021年02月09日 | 基于S3C6410的ARM11学习(十五) MMU来了

2021-02-09 来源:eefocus

如今,已经是到了main的世界了。下面就要来体验ARM11的MMU,这个东西在STM32中是没有的。之前在核心初始化过程中,是将MMU功能给关闭的。那是因为那个时候,操作的都是物理地址,所以需要将MMU关闭。


 MMU,内存管理单元。主要是有两个作用:


1、  将虚拟地址转化为物理地址

2、  内存的访问权限管理

         clip_image002

上面这个图就说明了MMU的作用。


有三个任务在运行,运行的地址都是0x400000,如果不进行处理,这肯定是不行的。所以加入了MMU,MMU其实就是一个页表。将虚拟地址通过查表的方式,对应到物理地址去。虽然三个任务的运行地址都是0x400000,但是这个地址是虚拟地址,在页表中,将每个任务的虚拟地址对应到不同的物理地址,这样,就实现了各个任务虽然是同一个虚拟地址,但是在不同的物理地址中运行。


所以要使用MMU,就首先要建立这个页表,这个页表是谁建立的,就是我们自己建立的。建立虚拟内存对应的物理内存的页表,这样,MMU才能从页表中去找到虚拟地址对应的物理地址。


MMU有一级转换和二级转换,其实就是查几次表。对于一级转换,就是只查一次页表,就确定了物理地址。这个在S3C6410中,方式是段映射。对于二级转换,就要查两次页表或者三次,才能确定物理地址,这个在S3C6410中。有两种方式,一种细页方式,一种粗页方式。这两种的区别就是每一页对应的大小不一样而已。

         clip_image004

上图是一级转换描述符。通过虚拟地址的[31:20],找到对应的转换描述符,这个转换描述符其实就是一个存在ram中的32位的一个数据。通过判断这个描述符的最后两位,判断是什么转换。如果是段转换,就按照段转换的格式去转化物理地址。如果是页转换,就在去找第二级的页表,然后再按照二级页表的格式去转化物理地址。


首先看下一级转换页表的段转换。

clip_image006

一级页表总包含4096个转换描述符。因为是通过虚拟地址的31:20位寻址的。12位能够表示的数最大是4096,所以说一级页表总共有4096个转换符。页表的首地址就是TTB,这个地址是很重要的,因为有了这个地址才能知道页表是存在什么地方的,才能通过偏移找到对应的描述符。所以,是有一个寄存器来保存这个地址的,这个寄存器就在CP15的c2寄存器。


通过虚拟地址的高12位偏移,找到页表中的对应描述符,判断描述符的最后两位,确定是什么转换。10的话就表示是段转换。


判断是段转换后,将描述符的高12位取出,这个就是物理的基地址,在和虚拟地址的后20位拼接,就得到对应的物理地址。


对于段转换,每一个段代表物理的1MB地址。为什么是1MB了。因为总共是有4096个描述符,而ARM11是32位的,所以能够表示的空间是4G,这样除下来,不就每一段就表示1MB空间了。

        

二级转换的原理也是一样的。只不过需要多查几次表。这里就大致画个细页的转换图。

clip_image008

就是通过不断的查表,然后得到物理地址。


目前学习是基于段转换的学习,所以下面就说下段转换。先来看看一级页表描述符。

clip_image010

最后两位来表示是什么转换。10是段转换。

B:表示是否使能write buffer

C:  表示是否开启cache

XN:

clip_image012

Domain: 用来说明该段属于哪一个域,ARM11共有16个域,每个域可以设定不同的权限。将段分配到某个域,就使这段的权限和设定的域权限一样。

P:表示段区间有ECC,ARM11不支持,所以这一位为0.

AP:访问权限,这个配合域,说明该段地址的访问权限。

TEX:这个目前不是很清楚作用。

APX: 提供额外的访问权限。

S: 表示区域是否共享。0不共享,1共享。这个手册上说,是为了多核使用的。目前用不到,设置为0.

nG:

clip_image014

NS:

Section base address:这个就是段的物理地址的高12位。


下图是访问权限

clip_image016

为了让空间能够读写,所以APX和AP[1:0]的值设置为011.


这里设置的访问权限,还要配合设置的域。ARM11支持16个域,由CP15的C3来设置。在ARM11核手册195页,有说明:

clip_image018

寄存器的每两个位对应一个区域,设置不同的值,对访问权限也不一样。设置为00或10的话,以访问就产生异常,01的话,需要检查MMU中设置的权限。设置为11,就是不进行访问权限的判断。都认为是可以访问的。


这里为了简单,通通设置为11。所以这个寄存器的值就是0xffffffff。


下面就要进行程序的设计了。

第一步,就是建立页表。都使用段映射的方式,那么就要将段映射的描述符写入到相应的内存中去。


首先将页表放在ddr的第一个位置,也就是0x50000000。所以需要将这个地址写入到TTB中。


这次就通过虚拟地址实现灯闪烁,所以需要建立GPIO寄存器的虚拟地址到物理地址映射。


其次,开启MMU后,使用的就是虚拟地址了,所以还要建立程序段的页表,不然一旦开启MMU,CPU去取指令,这个时候发出的就是虚拟地址,但是又没有建立虚拟地址到物理地址的映射表。这样的话,就取不到指令了,程序就崩溃了。所以还需要对代码区建立映射页表。代码区的映射就是将虚拟地址直接转换为物理地址使用。


先确定使用GPIO的两个寄存器地址

clip_image020

就更改前面8位的值。下面就要将这个地址给映射到0x7F000000区域去。

clip_image022

代码也是比较简单的。首先申明一个ttb指针,这个指针就指向一级表的基地址,也就是ddr的首地址,0x50000000。然后再申明两个变量,一个表示虚拟地址,一个表示物理地址。


根据前面的一级段描述符格式,往对应的内存单元写入数据即可。段描述符的高12位是物理地址的高12位,所以首先有一个物理地址和0xFFF00000与的操作,将物理地址的高12位写入到段描述符中。

后面的位就进行相应的配置即可。看看这个定义的宏。

clip_image024

设置为访问权限是11,也就是不进行访问权限的检查。将域设置为0。CACHE和write BUFFER都给关掉。因为这只是对一个寄存器的操作,没有必要使用CACHE和write BUFFER。


这里用宏定义的话,程序的易读性好好得多,当然也可以直接给这个描述符赋值,不用这种宏定义的方式,但是这样程序易读性就差了,因为要去查手册才能知道你赋这个值有什么用。

 

这里使用*(ttb + (vaddr >> 20))来对对应的页描述符进行赋值。在一级页表中,是通过虚拟地址的高12位来决定偏移是多少。高12位也就是位移20位,所以这里就是加上虚拟地址右移20位的值,也就是取出高12位的值。注意,这里是指针操作,假设这个时候虚拟地址的高12位值是5,那么写的地址不是0x50000005,而是0x50000014。因为指针的数据类型是long型,4个字节,所以加1,地址就会加4,加5,地址就会加5*4=20。


这样,就建立好了GPIO的页表。访问虚拟地址0xc7000000,也就是访问物理地址0x7f000000。整个段空间是1Mb。

接着就要建立代码区的页表。


这个时候,代码已经是在内存中运行的了。所以,直接将内存的所有地址空间进行映射,空间是64MB大小。

clip_image026

这里使用的宏

clip_image028

其实就是多一个开启CACHE和WRITE BUFFER。


内存映射是映射一片区域,从0x50000000地址开始到0x54000000这64M的虚拟地址给映射到0x50000000地址开始到0x54000000这64M物理地址上去。这样,即使使用虚拟地址去取ddr中数据,也是能够取到的。


因为一个段是映射的1MB空间,所以总共需要64个段,十六进制也就是0x40。所以在while里面判断是虚拟地址要小于0x54000000。再者,每一个段表示1MB空间,所以虚拟地址和物理地址都要加1MB。也就是0x100000。


这样,就将页表给建立好了。如果还需要使用其他地址区域,就都得为这些区域建立映射表。

下面就要来开启MMU了。


之前说过,有一个TTB是很重要的,保存的是一级页表的首地址。首先就应该先要设置这个TTB。往CP15的C2寄存器里面写入这个值就好了,因为这个寄存器就是保存的TTB。

然后是设置域的权限,将域的权限设置为11,不进行访问权限检查。设置CP15的c3寄存器。


最后打开MMU。设置CP15的c1寄存器组的c0。


是对CP15进行操作,用C语言是实现不了的,使用嵌入汇编。

clip_image030

这样,就设置好了MMU,并打开了MMU。之后使用的地址都是虚拟地址了。而且该虚拟地址必须是要在页表中建立的,不然的话,就会产生异常。


后面使用虚拟地址来让灯闪烁。

clip_image032

代码和之前代码一样,不过只是地址变量,寄存器使用的地址是虚拟地址了,也不是物理地址了。

clip_image034

总结一下,MMU的作用其实就是地址的转换,将虚拟地址转换为物理地址。不过在bootloader开发阶段,这个MMU是不使用的。因为在这阶段,要配置大量的寄存器来对硬件进行一些初始化,如果使用MMU的话,就要对这些寄存器的地址都要建立页表,使CPU能够访问到。这就比较麻烦了。不过在跑操作系统的时候,这个又是很需要的。这让内存管理变得方便。进程都使用虚拟地址,操作系统对这些虚拟地址进行映射到具体的物理地址上去,就感觉每个进程都是可以访问到4G空间的。


对比STM32:

STM32没有MMU,只有MPU,对内存保护。相当于实现了MMU的一半功能。

推荐阅读

史海拾趣

Comchip Technology公司的发展小趣事

Comchip Technology公司于2000年在新北市莺歌区创立,创始人凭借对半导体技术的深刻理解和前瞻眼光,决定专注于二极管制造技术的研发与创新。在创立初期,公司面临资金紧张、市场竞争激烈等挑战,但凭借卓越的技术实力和坚定的信念,成功开发出了一系列高质量的二极管产品,逐渐在市场中站稳脚跟。

Cermetek Microelectronics公司的发展小趣事

Cermetek Microelectronics公司在创立之初,便专注于微电子技术的研发与创新。创始人凭借在半导体领域的深厚背景,带领团队攻克了一系列技术难题,成功开发出具有高性能和稳定性的微电子产品。这些产品不仅满足了市场对微型化、高集成度的需求,更在多个关键领域实现了技术突破,为公司赢得了市场的初步认可。

CALMIRCO公司的发展小趣事

CALMIRCO公司深知合作共赢的重要性,因此积极与上下游企业建立紧密的合作伙伴关系。公司与多家知名芯片制造商、电子设备生产商等建立了长期稳定的合作关系,共同推动产业链的发展。通过资源共享、技术互补等方式,CALMIRCO公司与合作伙伴实现了共赢发展,共同提升了行业竞争力。

Delock公司的发展小趣事

Delock公司自创立之初,就致力于电子连接技术的研发。公司创始人李先生敏锐地洞察到市场对高性能、稳定可靠的电子连接设备的需求,于是带领团队投入大量资源进行技术研发。经过数年的努力,Delock公司成功开发出一种具有革命性意义的电子连接器,不仅传输速度快,而且耐用性高,迅速在市场上获得了认可。这一创新不仅为Delock公司带来了可观的利润,也为公司在电子行业树立了技术领先的形象。

Burr-Brown公司的发展小趣事

Burr-Brown公司,成立于1956年,初期仅有两名雇员,并得益于房地产开发商的支持。公司起初专注于制造模拟集成电路,第一年的销售总额为1600美元。创始人布朗怀揣雄心壮志,提出在一年内将厂房扩大到1200平方英尺,并期望销售收入能增长到7200美元。随着销售的稳步增长,公司不断迁往更大的设施,最终在1965年购买了附近的机场,为公司未来的成长奠定了坚实的基础。

GAIA Converter Inc公司的发展小趣事

位于广东东莞的锋鸣电子有限公司,自2010年成立以来,便明确了自己的市场定位——专注于汽车电子配件的研发与生产。随着汽车行业的快速发展,公司敏锐地捕捉到智能驾驶和车载娱乐系统对高质量电声器件的需求,迅速调整产品结构,推出了一系列符合市场需求的蜂鸣器、扬声器等产品。凭借精准的市场定位和优质的产品质量,锋鸣电子在汽车电子配件领域站稳了脚跟。

问答坊 | AI 解惑

一点建议

怎么上传不了很大的文件啊,比如视频啊几个G的,有什么办法改进没有啊…

查看全部问答>

AVR定时器的要点介绍

AVR定时器的要点介绍…

查看全部问答>

消费电子产品地域差异性日趋明显

前不久见到一位欧洲的朋友,偶然知道他随身携带一部便携式笔记本,由于无线网络问题在中国没有用武之地,听朋友介绍在无线网络相对发达的欧洲,这种便携式笔记本还是很受欢迎的。         同样的情况反映在智能手 ...…

查看全部问答>

招聘 Win CE软件开发工程师(北京)

主要开发WinCE下类 iPhone(Mutli-touch)技术的输入法    要求如下:   1. 熟悉windows ce或者Symbian下的编程,或熟练掌握 Windows API 编程,3年以上工作经验也可;   2. 精通C/C++语言;   3. 对U ...…

查看全部问答>

做过嵌入式,想做无线该怎么开始?

做了一年半的嵌入式,都是在别人基础上加功能,改UI,改驱动 想做无线方面,不知道怎么入手 希望高手指点…

查看全部问答>

请问如何更改WINCE 内核的按键音?

现在的按键音是生成内核时就有的,想改一个别的声音,请问该怎么改啊? 这个声音文件隐藏在哪里、有更改过这个按键音文件的朋友吗?…

查看全部问答>

Clock jitter analyzed in the time domain Part 1

本帖最后由 dontium 于 2015-1-23 13:39 编辑 IntroductionNewer high-speed ADCs e outfittedwith a large analog-input bandwidth (aboutthree to six times the maximum samplingfrequency) so they can be used in undersamplingapplications. ...…

查看全部问答>

给大家提个醒

用万利的演示板EK-STM3210E,编译器为MDK的, 最好不要用板的仿真器ST LINK II,一大堆莫名其妙的死机烦死人。 很多都死在HardFault_Handler(void)里,就是加一些没有调用的死代码也死, 编译时无任何错误提示。 换了一个山寨版的J-LINK, ...…

查看全部问答>

24c64连续读写子程序,其他部分在精华里!

void Read24C64(unsigned int ADDR,unsigned char *s,unsigned char no) { // uchar ddata=0; unsigned char ADDR_L,ADDR_H,i; ADDR_L=ADDR%256; ADDR_H=ADDR/256; IIC_START (); IIC_TX_DATA (0xA0); delay(50); IIC_TX_DATA (ADDR_H) ...…

查看全部问答>

大家帮忙看看我用中断实现的LED闪烁,但是为什么不行呢?

int main(void){         // disable JTAG port    DDPCONbits.JTAGEN = 0; //T2 interrupt initialization   SEI();//打开总中断    IFS0bits.T2IF=0;//清零中断标志位& ...…

查看全部问答>