单片机
返回首页

对s3c2440 mmu.c的分析

2022-05-23 来源:eefocus

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

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???

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 用NE555制作定时器

  • 如何调制IC555振荡器

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章