历史上的今天
今天是:2024年08月22日(星期四)
2019年08月22日 | ARM920T_内核MMU与cache应用分析
2019-08-22 来源:eefocus
一、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 = .;
}
下一篇:S3C2440代码重定位分析
史海拾趣
|
一.填空题 1. 在Linux系统中,以 方式访问设备 。 2. Linux内核引导时,从文件 中读取要加载的文件系统。 3. Linux文件系统中每个文件用 来标识。 4. 全部磁盘块由四个部分组成,分别为 。 5. 链接分为: 和 。 6. 超级块包含了 和 等重要的 ...… 查看全部问答> |
|
根据datasheet (nand flash controller)The S3C2416 is equipped with an internal SRAM buffer called ‘Steppingstone’. This supports NAND flash boot loader. When you use IROM boot and select nand flash as boo ...… 查看全部问答> |
|
求ADS8364在FPGA数据采集系统中的AD转换控制的verilog或VHDL程序代码 求ADS8364在FPGA数据采集系统中的AD转换控制的verilog或VHDL程序代码,急需希望大家帮助!… 查看全部问答> |
|
用ARM裸机实现多任务 采用定时器0来产生一个时间片timer,1timer=1us 接着达到某个时间(timer的n倍)时某个任务执行 然后每个任务都这样等待某个时间后执行 定时器0产生中断,代码如下 /****************************************************** ...… 查看全部问答> |
|
为什么我在evc中输出只有emulator可选,没有设备可选? 为什么我在evc中输出只有emulator可选,没有设备可选? 这样我就没法把程序download到wince设备上了?为什么? 是不是少装了什么?请各位帮帮忙.… 查看全部问答> |
|
[100分] Wince下修复SqlCE文件报错. 在线等. private void btnRepair_Click(object sender, EventArgs e) { SqlCeEngine engine = new SqlCeEngine(string.Format(\"Data Source = {0};password ...… 查看全部问答> |
|
求一完整程序~关于EVC4.0下的UDP编程!有的大大请加我QQ 41368886 还有哪个大大有Pocket PC 2002一Win32 (WINCE X 86) Debug 的开发环境也发给我! 求~~跪求这两个 … 查看全部问答> |




