对S3C2440 mmu.c的分析

/************************************************
NAME      : MMU.C
DESC   :
Revision : 1.0
************************************************/

#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "mmu.h"

// 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_DisableDCache();
MMU_DisableICache();

//If write-back is used,the DCache should be cleared.
for(i=0;i<64;i++)
   for(j=0;j<8;j++)
    MMU_CleanInvalidateDCacheIndex((i<<26)|(j<<5));
MMU_InvalidateICache();
   
#if 0
//To complete MMU_Init() fast, Icache may be turned on here.
MMU_EnableICache();
#endif
   
MMU_DisableMMU();
MMU_InvalidateTLB();

//MMU_SetMTT(int vaddrStart,int vaddrEnd,int paddrStart,int attr)
//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

//下面3条代码是对s3c2440虚拟地址映射到物理地址(内存)的操作,2440是bank6的。
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.
}   


// attr=RW_CB,RW_CNB,RW_NCNB,RW_FAULT
void ChangeRomCacheStatus(int attr)
{
int i,j;
MMU_DisableDCache();
MMU_DisableICache();
//If write-back is used,the DCache should be cleared.
for(i=0;i<64;i++)
   for(j=0;j<8;j++)
    MMU_CleanInvalidateDCacheIndex((i<<26)|(j<<5));
MMU_InvalidateICache();
MMU_DisableMMU();
MMU_InvalidateTLB();
MMU_SetMTT(0x00000000,0x07f00000,0x00000000,attr); //bank0
MMU_SetMTT(0x08000000,0x0ff00000,0x08000000,attr); //bank1
MMU_EnableMMU();
MMU_EnableICache();
MMU_EnableDCache();
}   
   

void MMU_SetMTT(int vaddrStart,int vaddrEnd,int paddrStart,int attr)
{
volatile U32 *pTT;
volatile int i,nSec;
pTT=(U32 *)_MMUTT_STARTADDRESS+(vaddrStart>>20);
nSec=(vaddrEnd>>20)-(vaddrStart>>20);
for(i=0;i<=nSec;i++)

*pTT++=attr |(((paddrStart>>20)+i)<<20);
}

//上面这个函数是分析的重点。vaddrstart是虚拟地址的起始地址,vaddrend是虚拟地址的结束地址,paddrstart是物理地址的开始地址,也就是把内存上从paddrstart开始到距离paddrstart ((vaddrend>>20)-(varrdstart>>20))的这部分内存空间映射到虚拟地址上。

以MMU_SetMTT(0x30000000,0x30100000,0x30000000,RW_CB);   //bank6-1 为例:

虚拟起始地址是0x30000000,结束地址是0x30100000,物理地址是0x3000000,RW_CB是对内存的访问权限控制。从0x30000000(起始地址)到0x300FFFFF的内存是1M,从0x30100000(结束地址)到0x301FFFFF又是1M,因此函数将0x30000000到0x30100000的虚拟地址映射到物理地址0x30000000开始的2M空间。参考下图:

对S3C2440 mmu.c的分析

函数中_MMUTT_STARTADDRESS的值是0x33ff8000这是我们从2^32的虚拟地址中取出做为映射物理地址的地址。

pTT=(U32 *)_MMUTT_STARTADDRESS+(vaddrStart>>20);得到的pTT为0x33ff8300,就是说2M的物理地址将从这里开始得到映射 。

nSec=(vaddrEnd>>20)-(vaddrStart>>20);得到的是对Translation Table中段(section)的索引(index),其中每段为1M。这里我们得到的nSec是1。


for(i=0;i<=nSec;i++) //i取到0和1,也就是两个段(2M)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwjxsj.html