当设置完时钟分频以后,uboot就会执行cpu_init_crit汇编函数,这个函数的主要作用就是关闭缓存和mmu,然后调用lowlevel_init函数进行系统总线的初始化。

为什么启动的时候,需要关闭缓存和mmu呢?我们先了解一下他们的作用。

缓存是主存(内存)和CPU通用寄存器之间设置的一个高速的、容量相对较小的存储器,把正在执行的指令地址附近的一部分指令或数据从主存调入这个存储器,供CPU在一段时间内使用,以提高程序的运行速度。

mmu可以实现虚拟内存和内存保护等功能,完成对内存的操作和管理。

CACHE是高速缓冲存储器。CPU工作速度是很快的,而外部内存是工作很慢的,所以当CPU对内存访问的时候,是要等待内存访问结束的。所以中间CPU就在等待,这就浪费了时间。所以在CPU和内存之间加一个CACHE,当CPU写数据到内存中的时候,就先写入到CACHE中,然后CACHE再写入到内存中。CPU写CACHE是很快的,所以就提高了写数据的效率。读数据的话,CPU先在CACHE中去找数据,没有找到的话,CACHE将数据从内存中取出来,再给CPU,同时把这个数据存起来。当CPU在CACHE中找到数据的话,就直接使用这个数据,就不用再去内存中取数据了。

Caches是CPU内部的一个2级缓存,它的作用是将常用的数据和指令放在CPU内部。Caches是通过CP15管理的,刚上电的时候,CPU还不能管理Caches。上电的时候指令Cache可关闭,也可不关闭,但数据Cache一定要关闭,否则可能导致刚开始的代码里面,去取数据的时候,从Cache里面取,而这时候RAM中数据还没有Cache过来,导致数据预取异常 。说到Caches就必须提到一个关键字Volatile,它的本质:是告诉编译器不要对我的代码进行优化,作用是让编写者感觉变量的变化情况。因为在优化时,会将常用的代码取出来放到Caches中,它没有从实际的物理地址去取,它直接从CPU的缓存中去取,但常用的代码就是为了检测一些常用变量的变化,如果正在取数据的时候发生跳变,那么就检测不到变量的变化了,所以在这种情况下要用Volatile关键字告诉编译器不要做优化,让cpu每次都从实际的物理地址中去取指令。其实这也是为什么要关闭数据缓存的原因,如果汇编指令读取的时候缓存中的数据,而实际物理地址的数据发生了变化,将导致cpu读取不到真实的最新的值。然而在C语言中是不会关闭Caches的,如果编写者要检测外界物理数据的变化,或变化太快,从Caches中取数据会有误差,就加一个关键字Volatile。

同样,在板子启动的时候是没有对mmu进行初始化的,而且这个时候也用不到mmu,为了避免他们影响启动时的初始化,所以需要先关闭mmu和缓存。

2440的协处理器CP15总共有c0~c15这16个协处理器寄存器,各自具有一定的功能定义。但总的来说,cp15主要跟以下功能有关:
1、获取device id和cache type等一些CPU相关信息。
2、MMU操作。包括MMU的使能和禁止,虚拟地址到物理地址的映射机制建立
3、访问权限控制。主要用来实现安全机制和linux的写时复制(copy on write)。
4、设置时钟模式。init.S中MMU_SetAsyncBusMode和MMU_SetFastBusMode这两个函数

和MMU有关的p15寄存器为c1(control register)和c2(TTB translation table base register)。其中c2比较简单,就是用来储存从虚拟地址到物理地址的地址转换表的基地址的(转换表存放在内存中,譬如可以放在0x30000000地址),因此我们在初始化mmu的时候,只要将规划的转换表基地址用mcr指令传送到该c2寄存器即可。而c1寄存器为控制寄存器,详细定义如下:

Register 1 - Control (read/write)
All values set to 0 at power-up.
o Bit 0 - On-chip MMU turned off (0) or on (1) 用来关闭或使能MMU
o Bit 1 - Address alignment fault disabled (0) or enabled (1) 关闭或打开地址对齐检查
o Bit 2 - Data cache turned off (0) or on (1) 数据cache打开或关闭
o Bit 3 - Write buffer turned off (0) or on (1)
o Bit 7 - Little-endian operation if 0, big-endian if 1 用来选择大小端格式
o Bit 8 - System bit - controls the MMU permission system
o Bit 9 - ROM bit - controls the MMU permission system bit8(S bit ) and bit9(R bit)用来管理MMU访问权限,第3部分会详述
o Bit 12 - Instruction cache turned off (0) or on (1)” 指令cache打开或关闭
o Bit 13 - Base location of exception registers. 0x00000000(0) or 0xffff0000(1)上电启动地址。
o Bit 14 - Round robin replacement ,random replacement(0) or round-robin replacement(1).不太懂这个
o Bit 15 ~ Bit29 reserved
o Bit 30 nF bit bit30 和 bit31共同用来决定总线模式。 iA:nF = 00 FastBus mode
o Bit 31 iA bit

Registe bits

Name

Function

Value

31

iA bit

Asynchronous clock select

见时钟模式表

30

nF bit

notFastBus select

见 时钟模式表

29:15

-

Reserved

Read = Unpredictable

Write = should be zero

14

RR bit

Round robin replacement

0 = Random replacement

1 = Round robin replacement

13

V bit

Base location of exception register(异常寄存器基地址)

0 = Low address = 0x0000 0000

1 = High address = 0xFFFF 0000

12

I bit

Instruction cache enable

0 = Instruction cache disable

1 = Instruction cache enable

11:10

-

Reserved

Read = 00

Write = 00

9

Rbit

ROM protection

见图1

8

Sbit

System protection

见图1

7

Bbit

Big-endian/little-endian

0 = Little-endian operation

1 = Big-endian operation

6:3

-

Reserved

Read = 1111

Write = 1111

2

C bit

Data cache enable

0 = data cache disable

1 = data cache enable

1

A bit

Alignment fault enable

Data address alignment fault checking

(地址对齐检查)

0 = 禁用地址对齐检查功能

1 = 使能地址对齐检查功能

0

M bit

MMU enable

0 = MMU disable

1 = MMU enable

结合以上对c1寄存器的位定义的分析,我们来看看下面这个函数:

  1. void MMU_Init(void) {
  2. __asm{
  3. mov r0,#0x30000000; // r0=TTBase 即页表的基地址 mcr p15,0,r0,c2,c0,0; // C2中存放地址转换表基地址
  4. mvn r0, #0; // 数据取反传送指令
  5. mcr p15,0,r0,c3,c0,0; // 访问类型为管理者权限
  6. mrc p15,0,r0,c1,c0,0; // 读出协处理器C1 orr r0,r0,#01; // 或操作,使最低位为1
  7. mcr p15,0,r0,c1,c0,0; // 给C1赋值 }
  8. }

函数中使用ARM寄存器r0作为和协处理器寄存器的接口。mcr p15,0,r0,c2,c0,0这句将r0中得值(0x30000000,这个是我们规划的转换表的基地址)放入(因此是mcr,所以是从ARM寄存器到p15协处理器寄存器)c2中。c2即是p15中的转换表基址。

  1. mrc p15,0,r0,c1,c0,0; // 读出协处理器C1 orr r0,r0,#01; // 或操作,使最低位为1
  2. mcr p15,0,r0,c1,c0,0; // 给C1赋值 典型的读-改-写三步操作,目的就是将c1寄存器的bit0置1而同时不影响其他位。根据上面的寄存器定义可知,c1的bit0为MMU enable or disable,因此该三句代码实际上是打开了MMU。(注意MMU打开前后,地址空间发生了变化。MMU打开前程序是工作在物理地址空间的,而MMU打开后程序便工作在了虚拟地址空间)

c1中跟MMU有关的还有data cache和instruction cache的打开和关闭,S bit和 R bit联合组成的访问权限控制等位。另外,c1中还有其他一些我们可能会用到的信息位。
譬如:Bit7用来选择大小端模式,bootloader中一般会有代码,通过设置该位来告知CPU当前板子使用的是little endian or big endian。(因为该位上电默认是0,因此默认的模式为小端模式。); Bit13为上电启动地址,也就是reset excetion复位异常的入口地址。上电默认也是0,因此默认的上电启动地址为0x00000000。当我们使用mcr指令将该位置1时,便可以将reset exception设置到 0xffff0000,记得这个好像是为了WinCE的移植支持设计的。

下面是uboot中关闭mmu和cache的cpu_init_crit函数:

/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/ #ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
/*
* flush v4 I/D caches
*/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ /*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
mcr p15, 0, r0, c1, c0, 0 /*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a lowlevel_init.S in your board directory.
*/
mov ip, lr bl lowlevel_init mov lr, ip
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

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

清除完cache中的数据后,就可以关闭mmu和cache了。

接下来就是跳转到lowlevel_init函数,进行其他的初始化。

关闭缓存和mmu(转)的更多相关文章

  1. (6)uboot具体解释——关闭缓存和mmu

    uboot具体解释--关闭缓存和mmu 当设置完时钟分频以后,uboot就会运行cpu_init_crit汇编函数,这个函数的主要作用就是关闭缓存和mmu.然后调用lowlevel_init函数进行系 ...

  2. jQuery ajax Load关闭缓存的方法

    [导读] 在jQuery ajax Load关闭缓存的方法很简单,我们只要在$ ajaxSetup中把cache: false就楞以了,当然我们还可以使用一个随机参数来实例了.简单介绍load(url ...

  3. 在Firefox浏览器中关闭缓存.命令

    在Firefox中关闭缓存 看看这里 在地址栏输入:about:config 然后在过滤器中输入:browser.cache.disk.enable 解释:When a page is loaded, ...

  4. React Native WebView关闭缓存

    React Native WebView关闭缓存 网上搜索没有找到关闭React Native下webview控件的缓存的方法,经测试找到解决方案,记录如下 核心思路:通过请求时设置请求头,使页面缓存 ...

  5. Thinkphp关闭缓存方法总结(转)

    ThinkPHP在数据缓存方面包括文件方式.共享内存方式和数据库方式在内的多种方式进行缓存,通过插件方式还可以增加以后需要的缓存类,让应用开发可以选择更加适合自己的缓存方式,从而有效地提高应用执行效率 ...

  6. Confluence 6 升级自定义的站点和空间关闭缓存

    Velocity 被配置在内存中使用缓存模板.当你在 Confluence 中编辑了页面的模板文件,Confluence 知道文件进行了编辑,将会重新从磁盘中载入模板文件.如果你直接在 Conflue ...

  7. uboot

    ******************************************day:2014/10/14**************************uboot************* ...

  8. Linux内核源码分析--内核启动之(1)zImage自解压过程(Linux-3.0 ARMv7) 【转】

    转自:http://blog.chinaunix.net/uid-25909619-id-4938388.html 研究内核源码和内核运行原理的时候,很总要的一点是要了解内核的初始情况,也就是要了解内 ...

  9. 该如何关闭thinkphp的缓存呢?有下面几种方法可参考:

    该如何关闭thinkphp的缓存呢?有下面几种方法可参考: (1)在配置文件中关闭缓存 在你的配置文件config.php文件中加上如下两句:   复制代码代码如下: 'TMPL_CACHE_ON'  ...

随机推荐

  1. MyEclipse启动慢的办法

    禁用myeclipse updating indexes MyEclipse 总是不停的在 Update index,研究发现Update index...是Maven在下载更新,但很是影响myecl ...

  2. apache svn subversion安装和配置(使用源码安装包方式)

    环境:虚拟机下centos7 1.下载安装包:http://subversion.apache.org/download.cgi 2.上传到指定文件夹并解压 3.安装依赖包 apr apr-utils ...

  3. 初识python第一天

    一.python简介 1.1 python的诞生 python的创始人吉多.范罗苏姆(Guido van Rossum),他在开发python语言之前曾使用过几年的ABC语言,ABC是一门主要用于教学 ...

  4. android 布局优化常用技巧

    android对多个模块都要是要的UI逻辑的致辞除了fragment之外,没有别的东西可以支持了, include,merge,viewstub只能支持公用的ui,但是这个通用支持不能包含逻辑(jav ...

  5. Giving Data Backup Option in Oracle Forms 6i

    Suppose you want to give the data backup option in Oracle Forms application to some client users, wh ...

  6. 将InfoObject作为信息提供者Characteristic is InfoProvider

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  7. Java 中的 static 使用之静态变量

    大家都知道,我们可以基于一个类创建多个该类的对象,每个对象都拥有自己的成员,互相独立.然而在某些时候,我们更希望该类所有的对象共享同一个成员.此时就是 static 大显身手的时候了!! Java 中 ...

  8. windows下开启mysql远程访问

    USE mysql;SELECT * FROM USER ; 直接修改user=root host=127.0.0.1为% FLUSH PRIVILEGES;

  9. Deep Learning 11_深度学习UFLDL教程:数据预处理(斯坦福大学深度学习教程)

    理论知识:UFLDL数据预处理和http://www.cnblogs.com/tornadomeet/archive/2013/04/20/3033149.html 数据预处理是深度学习中非常重要的一 ...

  10. FACADE

    1 意图:为子系统中的一组接口提供一个一直的界面,Facade模式定义了一个高层接口.这个接口使得这一子系统更加容易使用, 2 动机,便于不需要更多功能的人通过Facade 简化使用 3 适用性: . ...