分类: 嵌入式
2013-09-07 21:41:29
ARM920T的MMU和Cache都集成在CP15协处理器中
以下是CP15协处理器的寄存器列表(摘自[S3C2410用户手册]),和CPU核的r0到r15寄存器一样,协处理器寄存器也是用0到15来编号,在指令中用4个bit来表示寄存器编号,有些协处理器寄存器有影子寄存器,这种情况下对同一个编号的寄存器使用不同的选项读或者写实际上访问的是不同的寄存器,后文用到某个寄存器时会详细说明它的功能。
访问CP15寄存器的指令访问CP15寄存器指令的编码格式及语法说明如下:
31 28 |
27 24 |
23 21 |
20 |
19 16 |
15 12 |
11 8 |
7 5 |
4 |
3 0 |
cond |
1 1 1 0 |
opcode_1 |
L |
cr n |
rd |
1 1 1 1 |
opcode_2 |
1 |
crm |
说明: |
指 令 |
说 明 |
语法格式 |
mcr |
将ARM处理器的寄存器中的数据写到CP15中的寄存器中 |
mcr{ |
mrc |
将CP15中的寄存器中的数据读到ARM处理器的寄存器中 |
mcr{ |
CP15寄存器介绍CP15的寄存器列表如表所示。
寄存器编号 |
基本作用 |
在MMU中的作用 |
在PU中的作用 |
|
c0 c0 |
ID号寄存器(只读) 缓存类型寄存器 |
ID编码和cache类型
|
||
c1 |
全局控制寄存器 (使能/禁止MMU、cache、写缓冲)) |
各种控制位 |
||
c2 |
转换表基址寄存器(Translation Table Base --TTB)(设置变换表基地址(16k对齐)) |
地址转换表基地址 |
Cachability的控制位 |
|
c3 |
域访问控制寄存器(Domain access control )(设置16个域的访问权限) |
域访问控制位 |
Bufferablity控制位 |
|
c4 |
保留 |
保留 |
保留 |
|
c5 |
异常状态寄存器(fault status -FSR) |
内存失效状态 |
访问权限控制位 |
|
c6 |
异常地址寄存器(fault address -FAR) |
内存失效状态 |
保护区域控制 |
|
c7 高速缓存和写缓存寄存器 |
高速缓存和写缓存控制 |
|
||
c8 |
TLB操作寄存器操作TLB功能(无效统一TLB、无效指令或数据TLB |
TLB控制 |
保留 |
|
c9 缓存锁定寄存器 |
高速缓存锁定 |
|
||
c10 |
TLB 锁定寄存器 |
TLB锁定 |
保留 |
|
c11 |
保留 |
|||
c12 |
保留 |
|||
c13 |
进程PID |
进程标识符 |
||
c14 保留 |
|
|||
c15 |
测试配置及时钟配置寄存器 |
因不同设计而异 |
因不同设计而异 |
|
ARM处理器中CP15协处理器的寄存器
CP15系统控制协处理器
CP15 —系统控制协处理器 (the system control coprocessor)他通过协处理器指令MCR和MRC提供具体的寄存器来配置和控制caches、MMU、保护系统、配置时钟模式(在bootloader时钟初始化用到)
CP15的寄存器只能被MRC和MCR(Move to Coprocessor from ARM Register )指令访问
MCR{cond} p15,
MRC{cond}
p15,
其中L位用来区分MCR(L=1)和MRC(L=0)操作. CP15包括15个具体的寄存器如下
要注意有2个R0,根据MCR操作数2的不同传送不同的值,操作数为0则表示操作ID号寄存器,这也一个只读寄存器;操作数为1则表示操作缓存类型寄存器
-c0:ID号寄存器 这是一个只读寄存器,返回一个32位的设备ID号,具体功能参考ARM各个系列型号的的CP15 Register 0说明.
MRC
p15, 0,
以下为ID Code详细描叙(ARM926EJ-S); ARM920T Part Number为0x920,Architecture (ARMv4T) 为0x2具体可参照ARM各型号.
-c0:缓存类型寄存器(CACHE TYPE REGISTER),包含了caches的信息。读这个寄存器的方式是通过设置协处理操作码为1.
MRC
p15, 0,
ARM处理器中cache类型标识符寄存器的编码格式如下所示:
31 29 28 25 24 23 12 11 0 |
||||
0 0 0 |
属性字段 |
S |
数据cache相关属性 |
指令cache相关属性 |
其中控制字段位[28:25]的含义说明如下:
cache类型标识符寄存器的控制字段位[28:25]:
位 |
说明 |
位[28: 25] |
指定控制字段位[24: 0]指定的属性之外的cache的其他属性,详见表4-2 |
位[24] |
定义系统中的数据cache和指令cache是分开的还是统一的: 0 系统的数据cache和指令cache是统一的; 1 系统的数据cache和指令cache是分开的 |
位[23: 12] |
定义数据cache的相关属性,如果位[24]为0,本字段定义整个cache的属性 |
位[31: 24] |
定义指令cache的相关属性,如果位[24]为0,本字段定义整个cache的属性 |
其中控制字段位[28:25]的含义说明如下:
表4-2 cache类型标识符寄存器的控制字段位[28:25]
编 码 |
cache类型 |
cache内容清除方法 |
cache内容锁定方法 |
0b0000 |
写通类型 |
不需要内容清除 |
不支持内容锁定 |
0b0001 |
写回类型 |
数据块读取 |
不支持内容锁定 |
0b0010 |
写回类型 |
由寄存器C7定义 |
不支持内容锁定 |
0b0110 |
写回类型 |
由寄存器C7定义 |
支持格式A |
0b0111 |
写回类型 |
由寄存器C7定义 |
支持格式B |
写通类型:任一从CPU发出的写信号送到cache的同时,也写入主存,以保证主存的数据能同步地更新
写回类型:数据一般只写到cache,这样有可能出现cache中的数据得到 更新而主存中的数据不变的情况,但此时cache中设一标志地址及数据陈旧的信息,只有当cache中的数据被换出或者强制清空操作时,才将原更新的数据写入主存,这样保证了cache和主存中的数据保持一致。
控制字段位[23:12]和控制字段位[11:0]的编码格式相同,含义如下所示:
11 9 8 6 5 3 2 1 0 |
||||
0 0 0 |
cache容量 |
cache相联特性 |
M |
块大小 |
cache容量字段bits[8: 6]的含义如下所示:
编 码 |
M=0时含义(单位KB) |
M=1时含义(单位KB) |
0b000 |
0.5 |
0.75 |
0b001 |
1 |
1.5 |
0b010 |
2 |
3 |
0b011 |
4 |
6 |
0b100 |
8 |
12 |
0b101 |
16 |
24 |
0b110 |
32 |
48 |
0b111 |
64 |
96 |
cache相联特性字段bits[5: 3]的含义如下所示:
编 码 |
M=0时含义 |
M=1时含义 |
0b000 |
1路相联(直接映射) |
没有cache |
0b001 |
2路相联 |
3路相联 |
0b010 |
4路相联 |
6路相联 |
0b011 |
8路相联 |
12路相联 |
0b100 |
16路相联 |
24路相联 |
0b101 |
32路相联 |
48路相联 |
0b110 |
64路相联 |
96路相联 |
0b111 |
128路相联 |
192路相联 |
cache块大小字段bits[1: 0]的含义如下所示:
编 码 |
cache块大小 |
0b00 |
2个字(8字节) |
0b01 |
4个字(16字节) |
0b10 |
8个字(32字节) |
0b11 |
16个字(64字节) |
-c1 控制寄存器 (类型:ARMv3:只写,ARMv4:读写)
MRC p15,0,rn,c1,c0,0
MCR p15,0,rn,c1,c0,0
CP15中的寄存器C1的编码格式及含义说明如下:
31 16 |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
附加 |
L4 |
RR |
V |
I |
Z |
F |
R |
S |
B |
L |
D |
P |
W |
C |
A |
M |
位 |
说 明 |
M |
0:禁止MMU或者PU; 1:使能MMU或者PU |
A |
0:禁止地址对齐检查; 1:使能地址对齐检查 |
C |
0:禁止数据/整个cache;1:使能数据/整个cache |
W |
0:禁止写缓冲; 1:使能写缓冲 |
P |
0:异常中断处理程序进入32位地址模式;1:异常中断处理程序进入26位地址模式 |
D |
0:禁止26位地址异常检查;1:使能26位地址异常检查 |
L |
0:选择早期中止模型;1:选择后期中止模型 |
B |
0:little endian; 1:big endian |
S |
在基于MMU的存储系统中,本位用作系统保护 |
R |
在基于MMU的存储系统中,本位用作ROM保护 |
F |
0:由生产商定义 |
Z |
0:禁止跳转预测功能;1:使能跳转预测指令 |
I |
0:禁止Icache;1:使能Icache |
V |
0:选择低端异常中断向量0x0~0x1c;1:选择高端异常中断向量0xffff0000~ 0xffff001c |
RR |
0:常规的cache淘汰算法,如随机淘汰;1:预测性淘汰算法,如round-robin淘汰算法 |
L4 |
0:保持ARMv5以上版本的正常功能;1:将ARMv5以上版本与以前版本处理器兼容,不根据跳转地址的bit[0]进行ARM指令和Thumb状态切换:bit[0]等于0表示ARM指令,等于1表示Thumb指令 |
附加: |
注意:对于MMU,其实只和CP15的寄存器的0、1、8、9位有关
注意:
1.无论MMU是否被开启,都可以进行对齐检查,对齐检查在MMU的权限检查、地址映射前进行。
2.段描述符中的“AP”位进行权限检查或二级页表中的大页/小页描述符中的“ap3”、“ap2”和“ap1”位会结合该寄存器中的R/S位,决定如何进行访问权限检查。首先说明。段描述符的“AP”控制整个段1M的访问权限,大页描述符每个“apx”控制大页1/4内存的访问权限,即“ap3”对应大页高端的16KB;小页描述符与大页描述符类似;极小页中的“ap”就控制整个极小页。
3.Icache一般在MMU开启之后使用,此时页表中描述的C位用来表示一段内存是否可以被cache,C=1则表示说允许cache,否则不允许cache,但是即使MMU没有开启,Icache也是可以被使用的,这时CPU读取指令时所涉及的内存都被当做是允许cache的。为了提高效率,应该尽早开启Icache。
4.系统上电或复位时,Dcache中的内容是无效的,并且Dcache功能是关闭的,而write buffer中的内容也是被丢弃的,启动Dcache同时就开启了write buffer。Dcache必须在MMU开启之后才能被使用,因为开启MMU之后,才能使用页表中的描述符来定义一块内存如何使用Dcache和write buffer。
在实际编程中,要注意如下几点:
1)开启MMU之前,是无效Icache、Dcache和write buffer
2)关闭MMU之前,情况Icache、Dcache,即将“脏”数据写到主存中
3)如果代码有变,使无效Icache,这样CPU取指时会重新读取主存
4)使用DMA操作可以被cache的内存时,将内存的数据发送出去时,要清空cache,将内存的数据读入时,要使无效cache
5)改变页表中地址映射关系也要慎重考虑
6)开启Icache或Dcache时,要考虑Icache或Dcache中的内容是否与主存一致
7)对于I/O空间,不使用cache和write buffer
-c2 地址变换表基址寄存器
保存页表基地址
(类型:ARMv3:只写,ARMv4:读写)
位[31:14]:变换表基地址,定位界限为16KB
CP15中的寄存器C2保存的是页表的基地址,即一级映射描述符表的基地址。其编码格如下所示:
31 0 |
一级映射描述符表的基地址(物理地址) |
-c3 域访问控制寄存器:
该寄存器定义了ARM处理器的16个域。用来表示这个域是否进行权限检查
在描述符中德 Domain占据4个bit,用来表示这块内存属于下面定义的16个域中的哪个域。
(类型:ARMv3:只写,ARMv4:读写)
数据的含义如下:
00 无访问权限,任何访问将产生域错误
01 客户(Client)模式,根据段和页描述符的访问权限检验-----根据段描述符中的“AP”位进行权限检查或二级页表中的大页/小页描述符中的“ap3”、“ap2”、“ap1”位进行权限检查。
10 保留,目前相当于无访问权限
11 管理(Manager)模式,不进行权限检查,允许任何访问
-c5 故障状态寄存器:
(类型:ARMv3:只读,ARMv4:读写)
Bit[8]:0
Bits[7:4]:当错误发生时,确定16个域中(D15–D0) 哪个被访问。
Bits[3:0]:指出试图访问的类型
CP15中的寄存器C5是失效状态寄存器,编码格式如下所示:
31 9 8 7 4 3 0 |
|||
UNP/SBZP |
0 |
域标识 |
状态标识 |
|
|
|
|
其中,域标识bit[7:4]表示存放引起存储访问失效的存储访问所属的域。 状态标识bit[3:0]表示放引起存储访问失效的存储访问类型,该字段含义如表4-3所示(优先级由上到下递减)。
状态标识字段含义
引起访问失效的原因 |
状态标识 |
域标识 |
C6 |
||
终端异常(Terminal Exception) |
0b0010 |
无效 |
生产商定义 |
||
中断向量访问异常(Vector Exception) |
0b0000 |
无效 |
有效 |
||
地址对齐 |
0b00x1 |
无效 |
有效 |
||
一级页表访问失效 |
0b1100 |
无效 |
有效 |
||
二级页表访问失效 |
0b1110 |
有效 |
有效 |
||
基于段的地址变换失效 |
0b0101 |
无效 |
有效 |
||
基于页的地址变换失效 |
0b0111 |
有效 |
有效 |
||
基于段的存储访问中域控制失效 |
0b1001 |
有效 |
有效 |
||
基于页的存储访问中域控制失效 |
0b1101 |
有效 |
有效 |
||
基于段的存储访问中访问权限控制失效 |
0b1111 |
有效 |
有效 |
||
基于页的存储访问中访问权限控制失效 |
0b0100 |
有效 |
有效 |
||
基于段的cache预取时外部存储系统失效 |
0b0110 |
有效 |
有效 |
||
基于页的cache预取时外部存储系统失效 |
0b1000 |
有效 |
有效 |
||
基于段的非cache预取时外部存储系统失效 |
0b1010 有效 |
有效 |
|||
-c6 故障地址寄存器:
(类型:ARMv3:只读,ARMv4:读写)
上一次数据存取中止的地址
CP15中的寄存器C5是失效地址寄存器,编码格式如下所示:
31 0 |
失效地址(虚拟地址) |
-c7:缓存操作寄存器
CP15的C7寄存器用来控制cache和写缓存,它是一个只写寄存器,读操作将产生不可预知的后果。 访问CP15的C7寄存器的指令格式如下所示:
mcr p15, 0,
-c8 TLB功能寄存器(类型:只写):
CP15的C8寄存器用来控制清除TLB的内容,是只写寄存器,读操作将产生不可预知的后果。 访问CP15的C8寄存器的指令格式如下所示:
mcr p15, 0,
功能如下所示:
p ?无效指令TLB
p ?无效指令单一入口
p ?无效整个数据TLB
p ?无效数据单一入口
功能 |
opcode2 |
CRm |
Data |
指令 |
无效所有TLB |
0 |
111 |
0 |
MCR p15, 0, Rd, c8, c7, 0 |
无效单一入口 |
1 |
111 |
虚拟地址 |
MCR p15, 0, Rd, c8, c7, 1 |
无效整个指令TLB |
0 |
101 |
0 |
MCR p15, 0, Rd, c8, c5, 0 |
无效指令单一入口 |
1 |
101 |
虚拟地址 |
MCR p15, 0, Rd, c8, c5, 1 |
无效整个数据TLB |
0 |
110 |
0 |
MCR p15, 0, Rd, c8, c6, 0 |
无效数据单一入口 |
1 |
110 |
虚拟地址 |
MCR p15, 0, Rd, c8, c6, 1 |
-c9:缓存锁定寄存器
CP15的C9寄存器用于控制cache内容锁定。 访问CP15的C9寄存器的指令格式如下所示:
mcr p15, 0,
mrc p15, 0,
如果系统中包含独立的指令cache和数据cache,那么对应于数据cache和指令cache分别有一个独立的cache内容锁定寄存器,那么对应的数据cache和指令cache分别有一个独立的cache内容锁定寄存器,
CP15的C9寄存器有A、B两种编码格式。编码格式A如下所示:
31 32-W 31-W 0 |
|
cache组内块序号index |
0 |
其中index表示当下一次发生cache未命中时,将预取的存储块存入cache中该块对应的组中序号为index的cache块中。此时序号为0~index-1的cache块被锁定,当发生cache替换时,从序号为index到ASSOCIATIVITY的块中选择被替换的块。
编码格式B如下所示:
31 30 W W-1 0 |
||
L |
0 |
cache组内块序号index |
位 |
说 明 |
L=0 |
当发生cache未命中时,将预取的存储块存入cache中该块对应的组中序号为index的cache块中 |
位 |
说 明 |
L=1 |
如果本次写操作之前L=0,并且index值小于本次写入的index,本次写操作执行的结果不可预知;否则,这时被锁定的cache块包括序号为0~index-1的块,当发生cache替换时,从序号为index到ASSOCIATIVITY的块中选择被替换的块 |
-R10 TLB锁住寄存器:(类型:读写)
该寄存器用于控制TLB内容锁定。
访问C10寄存器的指令格式如下:
mcr p15, 0,
mrc p15, 0,
如果系统中包含独立的指令TLB和数据TLB,那么对应于数据TLB和指令TLB分别有一个独立的TLB内容锁定寄存器,< opcode_2>用来选择其中的某个寄存器:
< opcode_2>=1选择指令TLB的内容锁定寄存器;
< opcode_2>=0选择数据TLB的内容锁定寄存器
TLB锁定是一些ARM存储器系统的特性,它允许把特定的转换表搜索结果装载到TLB中。这种方式能否被后来的结果覆盖由寄存器R10决定。
如果TLB为分离的,该寄存器有2个
通过
例如:
mcr p15,0,r0,c10,c0,0 ;数据寄存器
mcr p15,0,r0,c10,c0,1 ;指令寄存器
如果TLB为统一的,寄存器只有1个存在,
例如:
mcr p15,0,r0,c10,c0,0 ;统一寄存器
辅助寄存器必须为c0
CP15的C10寄存器用于控制TLB内容锁定。 访问CP15的C10寄存器的指令格式如下所示: mcr p15, 0,
C10寄存器的编码格式如下:
31 30 32-W 31-W 32-2W 31-2W 1 0 |
|||
可被替换的条目起始地址的base |
下一个将被替换的条目地址victim |
0 |
P |
位 |
说 明 |
victim |
指定下一次TLB没有命中(所需的地址变换条目没有包含在TLB中)时,从内存页表中读取所需的地址变换条目,并把该地址变换条目保存在TLB中地址victim处 |
base |
指定TLB替换时,所使用的地址范围,从(base)到(TLB中条目数-1);字段victim的值应该包含在该范围内 |
P |
1:写入TLB的地址变换条目不会受使整个TLB无效操作的影响,一直保持有效;0:写入TLB的地址变换条目将会受到使整个TLB无效操作的影响 |
-c13:进程PID
C13寄存器用于快速上下文切换FCSE。
访问CP15的C13寄存器的指令格式如下所示:
mcr p15, 0,
mrc p15, 0,
C13寄存器的编码格式如下所示:
31 25 24 0 |
|
PID |
0 |
其中,PID表示当前进程的所在的进程空间块的编号,即当前进程的进程标识符,取值为0~127。
0:MVA(变换后的虚拟地址)= VA(虚拟地址),禁止FCSE(快速上下文切换技术),系统复位后PID=0;
!0:使能FCSE。
1. 禁止数据CACHE,将C15中寄存器的c1寄存器C[2]清零
mrc p15,0,r0,c1,c0,0
bic r0,r0,#(0x1<<2)
mcr p15,0,r0,c1,c0,0
2. 禁止代码CACHE,将C15中寄存器的c1寄存器I[12]清零
mrc p15,0,r0,c1,c0,0
bic r0,r0,#(0x1<<12)
mcr p15,0,r0,c1,c0,0
3. 禁止MMU,将C15中寄存器的c1寄存器M[0]清零
mrc p15,0,r0,c1,c0,0
bic r0,r0,#0x1
mcr p15,0,r0,c1,c0,0
4. 使数据及代码段CACHE无效
mcr p15,0,r0,c7,c7,0
5. 清空写缓冲区
mcr p15,0,r0,c7,c10,4
6. 使TLB整个页表无效
mcr p15,0,r0,c8,c7,0
7. 设置控制域
mcr p15,0,r0,c3,c0,0 R0->C3;
8. 设置进程PID号
mcr p15,0,r0,c13,c0,0
9. 设置页表基地址
mcr p15,0,r0,c2,c0,0 R0->C2
10. 计算描述符表并添加到TLB指定的内存单元中
由于一级页表由虚地址[31:20]进行索引,共计4096个为16k,由于TQ2440开发板为64M内存,故我们将其放在0x33ffc000处,即64M内存的最未端的16K内存中。
11. 在设置好页表描述符的基础上, 我们启用地址对齐功能,将C1寄存器A[1]赋值为1
mrc p15,0,r0,c1,c0,0
orr r0,r0,#(0x1<<1)
mcr p15,0,r0,c1,c0,0
12. 开启MMU功能,将C1寄存器M[0]赋值为1
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0x1
mcr p15,0,r0,c1,c0,0
13. 开启代码及数据CACHE,将C1寄存器C[2]位,I[12]位赋值为1
mrc p15,0,r0,c1,c0,0
bic r0,r0,#(0x1<<12+0x1<<2)
mcr p15,0,r0,c1,c0,0
以下为CP15的一些应用示例
U32 ARM_CP15_DeviceIDRead(void)
{
U32 id;
__asm { MRC P15, 0, id, c0, c0; }
return id;
}
void ARM_CP15_SetPageTableBase(P_U32 TableAddress)
{
__asm { MCR P15, 0, TableAddress, c2, c0, 0; }
}
void ARM_CP15_SetDomainAccessControl(U32 flags)
{
__asm { MCR P15, 0, flags, c3, c0, 0; }
}
void ARM_CP15_ICacheFlush()
{
unsigned long dummy;
__asm { MCR p15, 0, dummy, c7, c5, 0; }
}
void ARM_CP15_DCacheFlush()
{
unsigned long dummy;
__asm { MCR p15, 0, dummy, c7, c6, 0; }
}
void ARM_CP15_CacheFlush()
{
unsigned long dummy;
__asm { MCR p15, 0, dummy, c7, c7, 0; }
}
void ARM_CP15_TLBFlush(void)
{
unsigned long dummy;
__asm { MCR P15, 0, dummy, c8, c7, 0; }
}
void ARM_CP15_ControlRegisterWrite(U32 flags)
{
__asm { MCR P15, 0, flags, c1, c0; }
}
void ARM_CP15_ControlRegisterOR(U32 flag)
{
__asm {
mrc p15,0,r0,c1,c0,0
mov r2,flag
orr r0,r2,r0
mcr p15,0,r0,c1,c0,0
}
}
void ARM_CP15_ControlRegisterAND(U32 flag)
{
__asm {
mrc p15,0,r0,c1,c0,0
mov r2,flag
and r0,r2,r0
mcr p15,0,r0,c1,c0,0
}
}
void ARM_MMU_Init(P_U32 TableAddress)
{
ARM_CP15_TLBFlush();
ARM_CP15_CacheFlush();
ARM_CP15_SetDomainAccessControl(0xFFFFFFFF);
ARM_CP15_SetPageTableBase(TableAddress);
}
void Enable_MMU (void)
{
__asm {
mrc p15,0,r0,c1,c0,0
mov r2, #0x00000001
orr r0,r2,r0
mcr p15,0,r0,c1,c0,0
}
printf("MMU enabled\n");
}
void Disable_MMU (void)
{
__asm {
mrc p15,0,r0,c1,c0,0
mov r2, #0xFFFFFFFE
and r0,r2,r0
mcr p15,0,r0,c1,c0,0
}
printf("MMU disabled\n");
}