一、cache分类及应用场合
cache是内存和CPU之间的高速缓冲存储器,其分为icache(指令缓存)和dcache(数据缓存)。如果开启了cache,当CPU运行时会将正在运行的指令地址附近的指令或者数据调入cache,这样当运行下一条指令或用到下一条数据时直接从cache中查找,如果查找不到再访问内存,以此加快CPU执行速度。icache可以直接开启,而dcache需要开启MMU之后才能开启。
在启动文件中开启icache的代码可以放在时钟速度配置完成之后,代码如下:
bl enable_icache
enable_icache:
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0
mov pc, lr
二、MMU的应用
当CPU执行小的应用程序时,只要代码大小在芯片存储容量范围内,CPU每次都可以直接访问内存执行指令,但是当代码很大超出芯片存储容量时,则不能运行。此时需要MMU(内存管理单元),MMU可以将物理地址重映射,开启MMU之后CPU每次访问的都是虚拟地址,而每一个虚拟地址或者多个虚拟地址对应一个物理地址。32位的CPU虚拟地址范围为4G,映射方式为在物理存储地址上建立映射表。每个表有多个条目,每个条目大小1M,所以表的大小为: 条目数 = 4G/1M = 4096 ,一个条目32位占4Byte, 表大小 = 4096 * 4Byte = 16KB。因而只要在nand上占据16KB的空间即可重映射4G的访问范围。
CPU发出的VA(虚拟地址)经过CP13的C13转换为MVA(modified virtual address),MMU所看到的地址其实是MVA,通常外在来看不加以细分,权当VA处理。MMU常用section转换方式进行虚拟地址到物理地址的转换,其格式如下:
高12位为PA(物理地址)的高12位,AP设置访问权限(常设置为11,特权模式/用户模式下可读可写,所有模式下允许任何访问),domain(域设置,arm9有16个域,此处设置0选择域0),C(是否开启cache),B(是否开启Write buffer),其他位用默认值。
重映射代码如下:
#define MMU_SECDESC_AP (3<<10)
#define MMU_SECDESC_DOMAIN (0<<5)
#define MMU_SECDESC_NCNB (0<<2)
#define MMU_SECDESC_WB (3<<2)
#define MMU_SECDESC_TYPE ((1<<4) | (1<<1))
#define MMU_SECDESC_FOR_IO (MMU_SECDESC_AP | MMU_SECDESC_DOMAIN | MMU_SECDESC_NCNB | MMU_SECDESC_TYPE)
#define MMU_SECDESC_FOR_MEM (MMU_SECDESC_AP | MMU_SECDESC_DOMAIN | MMU_SECDESC_WB | MMU_SECDESC_TYPE)
#define IO 1
#define MEM 0
void create_secdesc(unsigned int *ttb, unsigned int va, unsigned int pa, int io)
{
int index;
index = va / 0x100000;
if (io)
ttb[index] = (pa & 0xfff00000) | MMU_SECDESC_FOR_IO;
else
ttb[index] = (pa & 0xfff00000) | MMU_SECDESC_FOR_MEM;
}
/*
* VA PA CB
* 0 0 00
* 0x40000000 0x40000000 11
*
* 64M sdram:
* 0x30000000 0x30000000 11
* ......
* 0x33f00000 0x33f00000 11
*
* register: 0x48000000~0x5B00001C
* 0x48000000 0x48000000 00
* .......
* 0x5B000000 0x5B000000 00
*
* Framebuffer : 0x33c00000
* 0x33c00000 0x33c00000 00
*
* link address:
* 0xB0000000 0x30000000 11
*/
void create_page_table(void)
{
/* ttb: translation table base */
unsigned int *ttb = (unsigned int *)0x32000000;
unsigned int va, pa;
int index;
/* 2.1 for sram/nor flash */
create_secdesc(ttb, 0, 0, IO);
/* 2.2 for sram when nor boot */
create_secdesc(ttb, 0x40000000, 0x40000000, MEM);
/* 2.3 for 64M sdram */
va = 0x30000000;
pa = 0x30000000;
for (; va < 0x34000000;)
{
create_secdesc(ttb, va, pa, MEM);
va += 0x100000;
pa += 0x100000;
}
/* 2.4 for register: 0x48000000~0x5B00001C */
va = 0x48000000;
pa = 0x48000000;
for (; va <= 0x5B000000;)
{
create_secdesc(ttb, va, pa, IO);
va += 0x100000;
pa += 0x100000;
}
/* 2.5 for Framebuffer : 0x33c00000 */
create_secdesc(ttb, 0x33c00000, 0x33c00000, IO);
/* 2.6 for link address */
create_secdesc(ttb, 0xB0000000, 0x30000000, MEM);
}
启动文件中代码如下:
/* 创建页表 */
bl create_page_table
/* 启动MMU */
bl mmu_enable
mmu_enable:
/* 把页表基址告诉cp15 */
ldr r0, =0x32000000
mcr p15, 0, r0, c2, c0, 0
/* 设置域为0xffffffff, 不进行权限检查 */
ldr r0, =0xffffffff
mcr p15, 0, r0, c3, c0, 0
/* 使能icache,dcache,mmu */
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #(1<<12) /* enable icache */
orr r0, r0, #(1<<2) /* enable dcache */
orr r0, r0, #(1<<0) /* enable mmu */
mcr p15, 0, r0, c1, c0, 0
mov pc, lr
有几个需要注意的关键点:
1. 由于代码重定位脚本中将nand中的代码重定位至0xB0000000,所以应该在重定位之前MMU进行地址的重映射,将0XB0000000映射到0X30000000,也就是nnad启动时SDRAM的起始地址,有关重定位参考此链接S3C2440代码重定位分析
2.在makefile时注意将mmu.c放至靠前的位置,必须在nand的前4K范围完成地址重映射,代码重定位,否则芯片将直接无法启动。
3.当使用NOR启动时,0地址映射时不能开启cache和write buffer。
代码重定位脚本:
SECTIONS{
. = 0xB0000000;
__code_start = .;
. = ALIGN(4);
.text : {*(.text)}
. = ALIGN(4);
.rodata : {*(.rodata)}
. = ALIGN(4);
.data : {*(.data)}
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) *(.COMMON) }
_end = .;
}
上一篇:ARM内存边界对齐以及sizeof问题
下一篇:S3C2440代码重定位分析
推荐阅读最新更新时间:2024-11-13 13:21
设计资源 培训 开发板 精华推荐
- 使用 Analog Devices 的 LTC2925CUF 的参考设计
- 基于GL823K的高颜值读卡器!
- NCV78723R1DAGEVB:NCV78723 子板
- STM8L的触摸感应库-评估板
- 使用 Analog Devices 的 LT1317BIS8 的参考设计
- AOZ1210AI-EVB,使用AOZ1210AI DC-DC单步降压转换器的评估板
- 具有STCH03 CC模式初级感应开关控制器的15W 5V输出USB适配器评估板
- 使用 ROHM Semiconductor 的 BD46231 的参考设计
- #第五届立创电子设计大赛#家用太阳能生态圈控制系统
- 65W、19V 交流转直流单输出笔记本电源