热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

uboot具体解释——关闭缓存和mmu

当设置完时钟分频以后,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就必须提到一个keywordVolatile,它的本质:是告诉编译器不要对我的代码进行优化,作用是让编写者感觉变量的变化情况。

由于在优化时,会将经常使用的代码取出来放到Caches中,它没有从实际的物理地址去取,它直接从CPU的缓存中去取。但经常使用的代码就是为了检測一些经常使用变量的变化,假设正在取数据的时候发生跳变,那么就检測不到变量的变化了,所以在这样的情况下要用Volatilekeyword告诉编译器不要做优化。让cpu每次都从实际的物理地址中去取指令。

事实上这也是为什么要关闭数据缓存的原因,假设汇编指令读取的时候缓存中的数据。而实际物理地址的数据发生了变化,将导致cpu读取不到真实的最新的值。

然而在C语言中是不会关闭Caches的。假设编写者要检測外界物理数据的变化。或变化太快,从Caches中取数据会有误差,就加一个keywordVolatile。

相同。在板子启动的时候是没有对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

R  bit

ROM protection

 见图1

8

S  bit

System protection

 见图1

7

B  bit

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寄存器的位定义的分析,我们来看看以下这个函数:
[cpp] view plaincopy
  1. void MMU_Init(void)  
  2. {  
  3.     __asm{  
  4.    
  5.         mov r0,#0x30000000;     // r0=TTBase 即页表的基地址  
  6.         mcr p15,0,r0,c2,c0,0;   // C2中存放地址转换表基地址  
  7.       
  8.         mvn r0, #0;             // 数据取反传送指令  
  9.         mcr p15,0,r0,c3,c0,0;   // 訪问类型为管理者权限  
  10.   
  11.     mrc p15,0,r0,c1,c0,0;   // 读出协处理器C1  
  12.     orr r0,r0,#01;          // 或操作。使最低位为1  
  13.     mcr p15,0,r0,c1,c0,0;   // 给C1赋值   
  14.     }     
  15. }  
函数中使用ARM寄存器r0作为和协处理器寄存器的接口。mcr p15,0,r0,c2,c0,0这句将r0中得值(0x30000000。这个是我们规划的转换表的基地址)放入(因此是mcr,所以是从ARM寄存器到p15协处理器寄存器)c2中。c2即是p15中的转换表基址。


[cpp] view plaincopy
  1.     mrc p15,0,r0,c1,c0,0;    // 读出协处理器C1  
  2.     orr r0,r0,#01;          // 或操作。使最低位为1  
  3.     mcr p15,0,r0,c1,c0,0;   // 给C1赋值   
  4.     典型的读-改-写三步操作,目的就是将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, #0mcr 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, 0bic 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) Alignorr r0, r0, #0x00001000 @ set bit 12 (I) I-Cachemcr 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, lrbl lowlevel_initmov lr, ipmov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

在关闭CACHE之前。须要要做一件事。就是要将CACHE的原有的数据给清掉。

由于有可能之前,里面就有一些数据了,这个操作也是由CP15下的一个寄存器控制的。

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

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



点击打开链接

点击打开链接

点击打开链接

点击打开链接




推荐阅读
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • c语言基础编写,c语言 基础
    本文目录一览:1、C语言如何编写?2、如何编写 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了MySQL表分区的创建、增加和删除方法,包括查看分区数据量和全库数据量的方法。欢迎大家阅读并给予点评。 ... [详细]
  • 如何搭建Java开发环境并开发WinCE项目
    本文介绍了如何搭建Java开发环境并开发WinCE项目,包括搭建开发环境的步骤和获取SDK的几种方式。同时还解答了一些关于WinCE开发的常见问题。通过阅读本文,您将了解如何使用Java进行嵌入式开发,并能够顺利开发WinCE应用程序。 ... [详细]
  • OO第一单元自白:简单多项式导函数的设计与bug分析
    本文介绍了作者在学习OO的第一次作业中所遇到的问题及其解决方案。作者通过建立Multinomial和Monomial两个类来实现多项式和单项式,并通过append方法将单项式组合为多项式,并在此过程中合并同类项。作者还介绍了单项式和多项式的求导方法,并解释了如何利用正则表达式提取各个单项式并进行求导。同时,作者还对自己在输入合法性判断上的不足进行了bug分析,指出了自己在处理指数情况时出现的问题,并总结了被hack的原因。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
    本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
  • 《2017年3月全国计算机等级考试二级C语言上机题库完全版》由会员分享,可在线阅读,更多相关《2017年3月全国计算机等级考试二级C语言上机题库完全版( ... [详细]
  • C语言自带的快排和二分查找
    Author🚹:CofCaiEmail✉️:cai.dongjunnexuslink.cnQQ😙:1664866311personalPage&#x ... [详细]
author-avatar
noise1969_366438
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有