现在的位置: 首页 > 综合 > 正文

对s3c2440 mmu.c的分析

2013年05月16日 ⁄ 综合 ⁄ 共 4435字 ⁄ 字号 评论关闭

/************************************************ 

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的分析 - chenfang7977 - 在路上

函数中_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)

       *pTT++=attr |(((paddrStart>>20)+i)<<20);将物理起始地址的高12位+index做为Translation Table中的section base address,再或上内存权限控制位,而后加上pTT就是最终的虚拟地址,再进入下个循环对下一个块进行映射。内存权限控制位在这里是RW_CB,查mmu.h得知

#define RW_CB   (AP_RW|DOMAIN0|CB|DESC_SEC)    //计算得RW_CB:1100 0001 1110,对应下图中的低12位(AP2位,Domain4位,Domain的值对应协处理器CP15中Control Register3:DOMAIN ACCESS CONTROL REGISTER 16个区域中的一个 ),这里AP是11,表明对supervision和user都是可读可写。Domain是0000,对应Control
Register3中的file0(区域0),file0中的两位决定了是否对该内存区域进行访问权限的检查。
对s3c2440 mmu.c的分析 - chenfang7977 - 在路上
C位(write-through (WT)模式)和B位(write-back (WB)模式)不是不能同时为1吗,为什么这里都设置为1???

抱歉!评论已关闭.