MMU功能解析
memory management unit 内存管理单元
有MMU单元是ARM芯片和单片机的重要区别之一。
1、将虚拟地址转化为物理地址
2、访问权限管理
当MMU关闭时,虚拟地址等于物理地址,但是当程序比较复杂时,必须使用MMU,程序中使用的都是虚拟地址。
MMU的使用如下图所示:
深入剖析地址转化
2440、6410和210有相同的MMU的工作原理,即虚拟地址向物理地址的转换方式相同。
转换图如下所示:
MMU的目的就是实现将32位虚拟地址转化为真正的物理地址。
ARM系统支持3种类型的地址转化:
1、段式转化
2、粗粒度页面转化
3、细粒度页面转化
TTB寄存器
MMU要自动进行虚拟地址到物理地址的转化,首先要找到一级页表,而一级页表的基地址(TTB:translation table base)则是保存在CP15的C2寄存器中。因此,当程序员创建好相应的页表后,需要将页表基地址写入该寄存器。
一级页表的结构:
一级页表由工程师创建,保存在内存中,基地址存放在cp15的C2寄存器中。
段式转化分析
如果一级页表项中最后两位为‘10’,接下的来转化过程将按照段方式来进行。
每个段是1MB,2^20B
细页转化
如果一级页表项中最后两位为’11’,接下的来转化过程将按照细页方式来进行。
参看上面的大图片
MMU配置与使用
段方式:
1、建立一级页表
2、写入TTB
3、打开MMU
代码编写:
//用于MMU段式转换的的一些宏定义,一级页表中的内容
#define MMU_FULL_ACCESS (3 << 10) /* 访问权限,可读可写 */
#define MMU_DOMAIN (0 << 5) /* 属于哪个域,放在0域 */
#define MMU_SPECIAL (1 << 4) /* 必须是1 */
#define MMU_CACHEABLE (1 << 3) /* cacheable */
#define MMU_BUFFERABLE (1 << 2) /* bufferable */
#define MMU_SECTION (2) /* 表示这是段描述符 */
#define MMU_SECDESC (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | MMU_SECTION)
#define MMU_SECDESC_WB (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | MMU_CACHEABLE | MMU_BUFFERABLE | MMU_SECTION)
//section description
void creat_page_table()
{
unsigned long *ttb = (unsigned long *)0x50000000; //TTB放在起始位置
unsigned long vaddr, paddr;
vaddr = 0xA0000000; //GPIO的虚拟地址,不需使用cache和写缓存
paddr = 0x7f000000;
*(ttb + (vaddr >> 20)) = (paddr & 0xFFF00000) | MMU_SECDESC;
vaddr = 0x50000000; //内存中不需要产生特别的虚拟地址
paddr = 0x50000000;
while (vaddr < 0x54000000)
{
*(ttb + (vaddr >> 20)) = (paddr & 0xFFF00000) | MMU_SECDESC_WB;
vaddr += 0x100000;
paddr += 0x100000;
}
}
void mmu_init() /* 使用存储器管理单元MMU */
{
//建立一级页表
creat_page_table();
__asm__(
/*设置TTB基地址,写入cp15的c2寄存器*/
"ldr r0, =0x50000000\n"
"mcr p15, 0, r0, c2, c0, 0\n"
/*不进行权限检查,设置cp15中的c3寄存器*/
"mvn r0, #0\n"
"mcr p15, 0, r0, c3, c0, 0\n"
/*使能MMU,修改最后一位为1*/
"mrc p15, 0, r0, c1, c0, 0\n"
"orr r0, r0, #0x0001\n"
"mcr p15, 0, r0, c1, c0, 0\n"
:
:
);
}