基于S3C6410的ARM11学习(七) 核心初始化之关闭MMU和CACHE
0赞在关闭了所有中断后,就要关闭MMU和CACHE了。因为这个时候,还在初始化环境,这两个东西是用不到的。所以就需要把他们都关闭,免得影响我们的初始化。
MMU是Memory Management Unit的缩写,中文名是存储器管理单元。主要是两个功能:
1、虚拟地址转换为物理地址
2、实现内存的保护
至于具体的MMU的一些知识,等后面用到了在说明了。目前,只需要将MMU给关掉即可。
这个时候,我们需要查看S3C6410的核ARM1176JZFS手册。在这里,我们要接触到一个系统控制处理器,CP15。也叫做协处理器。
手册中说明了,CP15系统控制处理器的作用,主要是6个:
1、整个系统的控制和配置
2、CACHE的配置和管理
3、TCM控制和管理
4、MMU控制和管理
5、DMA控制
6、系统运行监控
CP15共有16组寄存器。每一组寄存器有不同的功能。每一组寄存器下又有若干个寄存器。
至于这些寄存器的功能,在手册中有说明。不过手册是以功能划分寄存器的。如对应MMU功能。
图中,就列出了MMU功能对应的寄存器组。总共用到了c0,c2,c3,c5,c6,c8,c10,c13,c15这9组寄存器。但是也不是每一组寄存器组的所有寄存器都需要到,所有后面通过Opcode_1,CRm,Opcode_2来标识是对哪一个寄存器。
下面是对协处理器访问的用法
MCR指令是对协处理对应的寄存器下的某个寄存器写数据,写的数据放在Rd寄存器中。
MRC指令是对协处理对应的寄存器下的某个寄存器读数据,读的数据放在Rd寄存器中。
说明各个参数意义:
Opcode_1: 操作符1,协处理器行为操作码,对于CP15来说,
CRn:协处理器的寄存器组编号,编号从c0-c10。
Rd:寄存器编号,r0-r14.
Opcode_2:访问寄存器组下的寄存器提供附加信息
CRm:寄存器组下的寄存器编号。
上面参数,在对应功能的图中都有说明。例如:
我们要写TLB type Register,写的值存在r0寄存器中。
那么从图中,对应
参数 |
值 |
Opcode_1 |
0 |
CRn |
c0 |
Rd |
r0 |
Opcode_2 |
3 |
CRm |
c0 |
在使用MCR指令。
mcr p15,0,r0,c0,c0,3
这样,就将r0的值写入到TLB type Register中去了。
CACHE是高速缓冲存储器。CPU工作速度是很快的,而外部内存是工作很慢的,所以当CPU对内存访问的时候,是要等待内存访问结束的。所以中间CPU就在等待,这就浪费了时间。所以在CPU和内存之间加一个CACHE,当CPU写数据到内存中的时候,就先写入到CACHE中,然后CACHE再写入到内存中。CPU写CACHE是很快的,所以就提高了写数据的效率。读数据的话,CPU先在CACHE中去找数据,没有找到的话,CACHE将数据从内存中取出来,再给CPU,同时把这个数据存起来。当CPU在CACHE中找到数据的话,就直接使用这个数据,就不用再去内存中取数据了。
上面两个图就说明了有CACHE和没有CACHE的区别。
在初始化阶段,我们是不是用这CACHE的。
CACHE在ARM11中是分类两种的。一种是存储指令的,一种是存储数据的。
这个在S3C6410的数据手册中有说明。看出来,I/DCACHE大小是16KB。所以以下的操作要分开对ICACHE和DCACHE操作。
我们要对MMU,CACHE控制,所以这里就对CP15的MMU,CACHE功能进行配置。我们知道在ARM中,对任何功能配置都是通过寄存器配置的,所以就需要去配置CP15的MMU,CACHE功能开启和关闭的寄存器。
注意,这个时候,这个寄存器就不能去MMU,CACHE功能部分去找了。而要去找系统控制和配置里面去找了
这个寄存器就是c1寄存器组下的控制寄存器。
直接看这个寄存器的各个位的功能。
这里就截取图中一部分,因为这部分中和MMU,CACHE有关。
最后1位,就是MMU的开启和关闭了。当为0的时候,MMU是关闭的,为1的话,MMU就是打开的。所以这里我们要写入0.将MMU关掉。
该寄存器的第2位,是控制DCACHE的。0关掉。所以这里我们要写入0.将DCACHE关掉。
该寄存器的第12位,是控制ICACHE的。0关掉。所以这里我们要写入0,将ICACHE关掉。
在关闭CACHE之前,还要做一件事,就是要将CACHE的原有的数据给清掉。因为有可能之前,里面就有一些数据了。这个操作也是由CP15下的一个寄存器控制的。
首先找到CACHE相关的寄存器组。看出是c7.
在去看CP15的各个寄存器组的功能。
得知c7组下的c7寄存器是对CACHE数据无效操作的。
再在c7组下的c7寄存器中去找,有上面这张表。
表中都给了汇编指令,怎么对两个CACHE都无效掉。所以,在程序中就直接使用该汇编指令即可。这里Rd可以是任意,因为这里什么值对该命令是没有影响的。
下面就可以开始编写代码了
1、先对两个CACHE中的数据无效掉。使用手册中的汇编,这里Rd使用r0。
2、将CP15的控制寄存器的数据先读出来存在r0中。
3、对r0寄存器数据中第0位,第2为清零。
4、在将r0数据写入到控制寄存器中,这样,就实现了控制寄存器的MMU关闭和DCACHE关闭
5、程序返回。
这里,只是对DCACHE对应的位清零了,使DCACHE关闭,而没有使ICACHE对应的位清零,关闭ICACHE。对于这里,国嵌解释说,在初始化的时候,对ICACHE的要求没有DCACHE那么严格,可以不用关闭,也可以关闭,而DCACHE就必须关闭。至于为什么,目前也不清楚,因为现在也才是初学,等以后学习深了应该就知道了。现在学习,就先跟着前辈们的路走。
对比STM32,这两步就简单了,因为根本就不用做。为什么了,因为STM32中就没有两个东西。都没有了,你怎么操作他。
STM32没有MMU,所以,你在STM32上面就跑不出LINUX系统,因为不能将虚拟内存转换为物理内存。STM32对地址操作都是操作的物理地址。这样,就有很大的局限性。
就这样,我们就完成了核心初始化之关闭MMU和CACHE了。
文中若有什么错误,麻烦各位指出,我会虚心的更改的。以免误人学习。也欢迎各位与我交流。