21_MMU和Cache
1、Cache
1.1、数据读取过程
不启用cache时:cpu直接将地址发给sdram,sdram再返回数据;
启用cache时:cpu先将指令发给指令cache,若data cache中有相应数据直接返回数据,若无数据再取sdram中;

程序局部性原理:
数据读取过程:
读取和写数据模式:
协处理器操作:

1.2、编程
在start.s中:
。。。
。。。
/* 一旦设置PLL,就会锁定LOCK TIME知道PLL输出稳定
* 然后CPU工作在新的频率FCLK下
*/
/*使能协处理器****************************************************************/
bl enable_icache
/*设置内存:sp栈和分辨nor和nand启动****************************************************************/
/* 设置内存: sp 栈
* 分辨nor/nand启动
* 写0到0地址,在读出来
* 如果得到零,表示0地址上的内容被修改了,它对应RAM,这就是nand启动
* 否则就是nor启动
*/
。。。。
。。。。
/*死循环****************************************************************/
halt:
b halt
/*使能协处理器***************************************************************/
enable_icache:
/* 设置协处理器使能icache */
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #(1<<12) /* r0 |= (1<<12) */
mcr p15, 0, r0, c1, c0, 0
mov pc, lr
2、mmu
2.1、mmu的介绍及地址映射



域的概念:
MUA:
2.2、编程
2.2.1、在start.s中
。。。
。。。
/*初始化sdram****************************************************************/
/* 在main函数之前初始化sdram */
bl sdram_init
/*创建页表****************************************************************/
bl create_page_table
/*使能mmu****************************************************************/
bl mmu_enable
/*重定位程序****************************************************************/
/* 重定位text,rodata,data段整个程序 */
bl copy2sdram
。。。
。。。
/*使能mmu***************************************************************/
mmu_enable:
/* 1 把页表基址告诉cp15 */
ldr r0, =0x32000000
mcr p15, 0, r0, c2, c0, 0
/* 2 设置域为0xffffffff,不进行权限检查 */
ldr r0, =0xffffffff
mcr p15, 0, r0, c3, c0, 0
/* 3 使能icache, dcache, mmu */
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #(1<<12) /* enable icache :instruction cache */
orr r0, r0, #(1<<2) /* enable dcache :data cache */
orr r0, r0, #(1<<0) /* enable mmu */
mcr p15, 0, r0, c1, c0, 0
mov pc, lr
2.2.2、在mmu.c中
#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
/* 根据va,pa设置页表条目 */
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)
{
/* 1 页表在哪?0x32000000(占据16KB)*/
/* ttb: translation table base */
unsigned int *ttb = (unsigned int *)0x32000000;
unsigned int va, pa;
int index;
/* 2 根据va,pa设置页表条目 */
/* 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 sram when nor boot 64MB 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 <= 0x5B00001C;)
{
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);
}
版权声明:本文为God__Rain原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。