weiqi7777

基于S3C6410的ARM11学习(七) 核心初始化之关闭MMU和CACHE

0
阅读(3956)

在关闭了所有中断后,就要关闭MMUCACHE了。因为这个时候,还在初始化环境,这两个东西是用不到的。所以就需要把他们都关闭,免得影响我们的初始化。

MMUMemory Management Unit的缩写,中文名是存储器管理单元。主要是两个功能:

1、虚拟地址转换为物理地址

2、实现内存的保护


至于具体的MMU的一些知识,等后面用到了在说明了。目前,只需要将MMU给关掉即可。

这个时候,我们需要查看S3C6410的核ARM1176JZFS手册。在这里,我们要接触到一个系统控制处理器,CP15。也叫做协处理器。

clip_image002

手册中说明了,CP15系统控制处理器的作用,主要是6个:

1、整个系统的控制和配置

2、CACHE的配置和管理

3、TCM控制和管理

4、MMU控制和管理

5、DMA控制

6、系统运行监控


CP15共有16组寄存器。每一组寄存器有不同的功能。每一组寄存器下又有若干个寄存器。

至于这些寄存器的功能,在手册中有说明。不过手册是以功能划分寄存器的。如对应MMU功能。

clip_image004

图中,就列出了MMU功能对应的寄存器组。总共用到了c0,c2,c3,c5,c6,c8,c10,c13,c159组寄存器。但是也不是每一组寄存器组的所有寄存器都需要到,所有后面通过Opcode_1CRmOpcode_2来标识是对哪一个寄存器。


下面是对协处理器访问的用法

clip_image006

MCR指令是对协处理对应的寄存器下的某个寄存器写数据,写的数据放在Rd寄存器中。

MRC指令是对协处理对应的寄存器下的某个寄存器读数据,读的数据放在Rd寄存器中。


说明各个参数意义:

Opcode_1: 操作符1协处理器行为操作码,对于CP15来说,永远为0b000

CRn:协处理器的寄存器组编号,编号从c0-c10

Rd寄存器编号,r0-r14.

Opcode_2访问寄存器组下的寄存器提供附加信息

CRm寄存器组下的寄存器编号。


上面参数,在对应功能的图中都有说明。例如:

我们要写TLB type Register,写的值存在r0寄存器中。

clip_image008

那么从图中,对应

参数

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再写入到内存中。CPUCACHE是很快的,所以就提高了写数据的效率。读数据的话,CPU先在CACHE中去找数据,没有找到的话,CACHE将数据从内存中取出来,再给CPU,同时把这个数据存起来。当CPUCACHE中找到数据的话,就直接使用这个数据,就不用再去内存中取数据了。

clip_image010

上面两个图就说明了有CACHE和没有CACHE的区别。

在初始化阶段,我们是不是用这CACHE的。


CACHEARM11中是分类两种的。一种是存储指令的,一种是存储数据的。

clip_image012

这个在S3C6410的数据手册中有说明。看出来,I/DCACHE大小是16KB。所以以下的操作要分开对ICACHEDCACHE操作。


我们要对MMUCACHE控制,所以这里就对CP15MMUCACHE功能进行配置。我们知道在ARM中,对任何功能配置都是通过寄存器配置的,所以就需要去配置CP15MMUCACHE功能开启和关闭的寄存器。

注意,这个时候,这个寄存器就不能去MMU,CACHE功能部分去找了。而要去找系统控制和配置里面去找了

这个寄存器就是c1寄存器组下的控制寄存器。

clip_image014

直接看这个寄存器的各个位的功能。

这里就截取图中一部分,因为这部分中和MMUCACHE有关。

clip_image016

clip_image018


最后1位,就是MMU的开启和关闭了。当为0的时候,MMU是关闭的,为1的话,MMU就是打开的。所以这里我们要写入0.MMU关掉。

该寄存器的第2位,是控制DCACHE的。0关掉。所以这里我们要写入0.DCACHE关掉。

该寄存器的第12位,是控制ICACHE的。0关掉。所以这里我们要写入0,将ICACHE关掉。


在关闭CACHE之前,还要做一件事,就是要将CACHE的原有的数据给清掉。因为有可能之前,里面就有一些数据了。这个操作也是由CP15下的一个寄存器控制的。

clip_image020

首先找到CACHE相关的寄存器组。看出是c7.

clip_image022

在去看CP15的各个寄存器组的功能。

得知c7组下的c7寄存器是对CACHE数据无效操作的。


clip_image024

再在c7组下的c7寄存器中去找,有上面这张表。

表中都给了汇编指令,怎么对两个CACHE都无效掉。所以,在程序中就直接使用该汇编指令即可。这里Rd可以是任意,因为这里什么值对该命令是没有影响的。


下面就可以开始编写代码了


clip_image026

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对地址操作都是操作的物理地址。这样,就有很大的局限性。

就这样,我们就完成了核心初始化之关闭MMUCACHE了。

文中若有什么错误,麻烦各位指出,我会虚心的更改的。以免误人学习。也欢迎各位与我交流。

Baidu
map