1. 什么是MMU?
参考:https://blog.youkuaiyun.com/p1279030826/article/details/105827355
1.1 背景与发展
- 随着计算机科学技术的发展,所需解决的问题越来越复杂,单任务批处理已不能满足需求了。
- 应用程序需要的内存量越来越大。
- 虚拟内存的思想。
- 程序所需的内存可以远超物理内存的大小,将当前需要执行的留在内存中,而不需要执行的部分留在磁盘中。
- 可以满足多应用程序同时驻留内存能并发执行。
1.2 MMU
- 内存管理单元(Memory Management Unit)。
- 为编程提供方便统一的内存空间抽象。
- 以最小的开销换取性能最大化。(利用 MMU 管理内存肯定不如直接对内存进行访问效率高)
- 节省内存, 物理内存成本高,CPU直接寻址空间有限。
1.3 TLB
- TLB(Translation Lookaside Buffer)转译后备缓冲器
- 本质上是 MMU 用于虚拟地址到物理地址转换表的缓存
2. S3C2440中的MMU
- 可以看到下图中,ARM9处理器核心可以经过MMU对内存空间进行访问。
- ARM920T 实现了 MMU,AMBA 总线和哈佛结构高速缓冲体系结构。
- 增强型 ARM 架构 MMU 以支持 WinCE,EPOC 32 和 Linux。
3. MMU代码
参考链接:https://www.docin.com/p-683073294.html
// 1) Only the section table is used.
// 2) The cachable/non-cachable area can be changed by MMT_DEFAULT value.
// The section size is 1MB.
extern char __ENTRY[];
void MMU_Init(void)
{
int i,j;
//========================== IMPORTANT NOTE =========================
//The current stack and code area can't be re-mapped in this routine.
//当前堆栈和代码区域不能在此例程中重新映射。
//If you want memory map mapped freely, your own sophiscated MMU initialization code is needed.
//如果您希望自由映射内存映射,则需要您自己复杂的 MMU 初始化代码。
//===================================================================
MMU_DisableDCache(); //1. 关闭数据高速缓存
MMU_DisableICache(); //2. 关闭指令高速缓存
//If write-back is used,the DCache should be cleared.
//如果使用回写,则应清除 DCache。
for(i=0;i<64;i++)
for(j=0;j<8;j++)
MMU_CleanInvalidateDCacheIndex((i<<26)|(j<<5)); //3. 清除数据高速缓存
MMU_InvalidateICache();//4. 废除指令高速缓存
#if 0
//To complete MMU_Init() fast, Icache may be turned on here.
//为了快速完成MMU_Init(),这里可以开启Icache。
MMU_EnableICache();
#endif
MMU_DisableMMU(); //5. 关闭MMU
MMU_InvalidateTLB(); //6. 废除 转译后备缓冲器TLB
//7. MMU设置转译表TT(虚拟起始地址,虚拟结束地址,物理起始地址,访问属性)
//转译表Translation Table
//把内存上从 物理起始地址(paddrstart) 开始,到 (物理起始地址 + 虚拟结束 -虚拟起始) 的内存,映射到虚拟地址上。
//MMU_SetMTT(0x00000000,0x07f00000,0x00000000,RW_CNB); //bank0
MMU_SetMTT(0x00000000,0x03f00000,(int)__ENTRY,RW_CB); //bank0
MMU_SetMTT(0x04000000,0x07f00000,0,RW_NCNB); //bank0
MMU_SetMTT(0x08000000,0x0ff00000,0x08000000,RW_CNB); //bank1
MMU_SetMTT(0x10000000,0x17f00000,0x10000000,RW_NCNB); //bank2
MMU_SetMTT(0x18000000,0x1ff00000,0x18000000,RW_NCNB); //bank3
//MMU_SetMTT(0x20000000,0x27f00000,0x20000000,RW_CB); //bank4
MMU_SetMTT(0x20000000,0x27f00000,0x20000000,RW_CNB); //bank4 for STRATA Flash
MMU_SetMTT(0x28000000,0x2ff00000,0x28000000,RW_NCNB); //bank5
//30f00000->30100000, 31000000->30200000
MMU_SetMTT(0x30000000,0x30100000,0x30000000,RW_CB); //bank6-1
MMU_SetMTT(0x30200000,0x33e00000,0x30200000,RW_NCNB); //bank6-2
//
MMU_SetMTT(0x33f00000,0x33f00000,0x33f00000,RW_CB); //bank6-3
MMU_SetMTT(0x38000000,0x3ff00000,0x38000000,RW_NCNB); //bank7
MMU_SetMTT(0x40000000,0x47f00000,0x40000000,RW_NCNB); //SFR
MMU_SetMTT(0x48000000,0x5af00000,0x48000000,RW_NCNB); //SFR
MMU_SetMTT(0x5b000000,0x5b000000,0x5b000000,RW_NCNB); //SFR
MMU_SetMTT(0x5b100000,0xfff00000,0x5b100000,RW_FAULT);//not used
MMU_SetTTBase(_MMUTT_STARTADDRESS);
MMU_SetDomain(0x55555550|DOMAIN1_ATTR|DOMAIN0_ATTR);
//DOMAIN1: no_access, DOMAIN0,2~15=client(AP is checked)
MMU_SetProcessId(0x0);
MMU_EnableAlignFault();
MMU_EnableMMU();
MMU_EnableICache();
MMU_EnableDCache(); //DCache should be turned on after MMU is turned on.
}
3.1 空间划分
- 首先必须要点出,虚拟结束地址也被包括在划分区域内,且向后1MB的空间(1个扇区的大小是1MB)。
3.2 内存芯片
- 开发板具有两块32MB的内存芯片组成。(2x32MB = 64MB)
- HY57V561620T 是一款 268,435,456 位 CMOS 同步 DRAM,非常适合需要大内存密度和高带宽的主内存应用。
- HY57V561620 被组织成 4Banks x 4Mbits x16。
- BA0,BA1表示Bank Adress。
- A0-A12:Row Address : RA0 ~ RA12 。Column Address : CA0 ~ CA8 。Auto-precharge flag : A10。
- UDQM, LDQM。读取模式下控制输出缓冲区。写入模式下屏蔽输入数据。
- 空间大小:4Bank x (行213 x 列29)x 16bit Data = 33554432Byte = 32MB。
3.3 实际接线
- 如下图所示,2块内存芯片。
- 从上图我们可以看出,S3C2440的ADDR2接在内存芯片的A0上。
- 地址有效变化的最小值 0x100,4( LADDR2=1),对应16bit x 2 = 32bit = 4字节。(LADDR0,LADDR1变化无效)。这也是设计上故意为之,为的是让地址和数据对应,地址变化4,对应新的32位数据。
3.4 分析MMU代码
1. 内存芯片的地址信息?
精彩稍后继续
2. 其他地址信息
4. 芯片资料
https://download.youkuaiyun.com/download/Kshine2017/74665645