ARM920T_内核MMU与cache应用分析

一、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 = .;
}

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值