📄 mmu.c
字号:
/************************************************
NAME : MMU.C
DESC :
Revision: 2002.2.28 ver 0.0
************************************************/
//#include "def.h"
#include "option.h"
#include "def.h"
//#include "2410addr.h"
//#include "2410lib.h"
//#include "2410slib.h"
#include "mmu.h"
#include "AT91RM9200.h"
#include "mmu_arm920t.h"
#include "console.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.
//*----------------------------------------------------------------------------
//* \fn AT91F_CleanDCache
//* \brief Clean and invalidate D Cache
//*----------------------------------------------------------------------------
void AT91F_CleanDCache()
{
register char seg, index;
for (seg = 0; seg < 8; ++seg) {
for (index = 0; index < 64; ++index) {
AT91F_ARM_CleanDCacheIDX((index << 26) | (seg << 5));
}
}
}
//*----------------------------------------------------------------------------
//* \fn AT91F_ResetICache
//* \brief Reset I Cache (Should be run from a non cachable area)
//*----------------------------------------------------------------------------
void AT91F_ResetICache()
{
// Flush I TLB
AT91F_ARM_InvalidateITLB();
// Flush I cache
AT91F_ARM_InvalidateICache();
}
//*----------------------------------------------------------------------------
//* \fn AT91F_ResetDCache
//* \brief Reset D Cache (Should be run from a non cachable area)
//*----------------------------------------------------------------------------
void AT91F_ResetDCache()
{
// Achieve pending write operations
AT91F_CleanDCache();
// Flush write buffers
AT91F_ARM_DrainWriteBuffer();
// Flush D TLB
AT91F_ARM_InvalidateDTLB();
// Flush D cache
AT91F_ARM_InvalidateDCache();
}
//*----------------------------------------------------------------------------
//* \fn AT91F_EnableMMU
//* \brief Enable MMU
//*----------------------------------------------------------------------------
void AT91F_EnableMMU()
{
unsigned int ctl;
ctl = AT91F_ARM_ReadControl();
ctl |= (1 << 0);
AT91F_ARM_WriteControl(ctl);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DisableMMU
//* \brief Disable MMU
//*----------------------------------------------------------------------------
void AT91F_DisableMMU()
{
unsigned int ctl;
ctl = AT91F_ARM_ReadControl();
ctl &= ~(1 << 0);
AT91F_ARM_WriteControl(ctl);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_EnableICache
//* \brief Enable I Cache
//*----------------------------------------------------------------------------
void AT91F_EnableICache()
{
unsigned int ctl;
ctl = AT91F_ARM_ReadControl();
ctl |= (1 << 12);
AT91F_ARM_WriteControl(ctl);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DisableICache
//* \brief Disable I Cache
//*----------------------------------------------------------------------------
void AT91F_DisableICache()
{
unsigned int ctl;
ctl = AT91F_ARM_ReadControl();
ctl &= ~(1 << 12);
AT91F_ARM_WriteControl(ctl);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_EnableDCache
//* \brief Enable D Cache
//*----------------------------------------------------------------------------
void AT91F_EnableDCache()
{
unsigned int ctl;
ctl = AT91F_ARM_ReadControl();
ctl |= (1 << 2);
AT91F_ARM_WriteControl(ctl);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_DisableDCache
//* \brief Disable D Cache
//*----------------------------------------------------------------------------
void AT91F_DisableDCache()
{
unsigned int ctl;
ctl = AT91F_ARM_ReadControl();
ctl &= ~(1 << 2);
AT91F_ARM_WriteControl(ctl);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_LockITLB
//* \brief Lock one I TLB entry after entries previously locked
//*----------------------------------------------------------------------------
void AT91F_LockITLB(unsigned int address)
{
// Set the P bit
AT91F_ARM_WriteITLBLockdown( 1); // base 0 victim 0 P 1
// Prefetch the instruction assuming an ITLB miss occurs, the entry base is loaded
AT91F_ARM_PrefetchICacheLine(address);
// Update base and victim values
AT91F_ARM_WriteITLBLockdown((1 << 26) | (1 << 20)); // base 1 victim 1 P 0
}
//*----------------------------------------------------------------------------
//* \fn AT91F_ARM_WriteITLBLockdown
//* \brief Write I TLB lockdown (Should be run from a non cachable area)
//*----------------------------------------------------------------------------
void AT91F_LockICache(unsigned int startAddress, unsigned int size)
{
unsigned int victim = 0;
AT91F_ARM_InvalidateICache();
AT91F_ARM_WriteICacheLockdown((victim++) << 26);
while (size) {
// Prefetch ICache line
AT91F_ARM_PrefetchICacheLine(startAddress);
startAddress += 32;
// Test for segment 0, and if so increment victim pointer
if ( !(startAddress & 0xE0) )
AT91F_ARM_WriteICacheLockdown((victim++) << 26);
size -= 32;
}
// If segment != 0 the increment victim pointer
if ( (startAddress & 0xE0) )
AT91F_ARM_WriteICacheLockdown(victim << 26);
}
void MMU_Init(void)
{
unsigned int i,j;
unsigned int *pTranslationTable=(unsigned int *)_MMUTT_STARTADDRESS;
AT91F_DisableICache();
AT91F_DisableDCache();
AT91F_ARM_WriteTTB((unsigned int) pTranslationTable);
AT91F_ARM_WriteDomain(0xC0000000);
// Reset table entries
for (i = 0; i < 4096; ++i)
pTranslationTable[i] = 0;
AT91F_DisableMMU();
// Program level 1 page table entry
// ((0x201+i) << 20) | // Physical Address
for(i=0;i<0x200;i++)
pTranslationTable[i] =
((0x201+i) << 20) | // Physical Address
(1 << 10) | // Access in supervisor mode
(15 << 5) | // Domain
1 << 4 |
0x2;
for(i=0x200;i<0x400;i++)
pTranslationTable[i] =
(i << 20) | // Physical Address
(1 << 10) | // Access in supervisor mode
(15 << 5) | // Domain
1 << 4 |
0xe;
/*for(i=0x204;i<0x300;i++)
pTranslationTable[i] =
(i << 20) | // Physical Address
(1 << 10) | // Access in supervisor mode
(15 << 5) | // Domain
1 << 4 |
0x2;
for(i=0x300;i<0x400;i++)
pTranslationTable[i] =
((i+0x100) << 20) | // Physical Address
(1 << 10) | // Access in supervisor mode
(15 << 5) | // Domain
1 << 4 |
0x2; */
for(i=0x400;i<0xF00;i++)
pTranslationTable[i] =
(i << 20) | // Physical Address
(1 << 10) | // Access in supervisor mode
(15 << 5) | // Domain
1 << 4 |
0x2;
for(i=0xF00;i<=0xFFF;i++)
pTranslationTable[i] =
(i << 20) | // Physical Address
(1 << 10) | // Access in supervisor mode
(15 << 5) | // Domain
1 << 4 |
0x2;
AT91F_EnableMMU();
AT91F_EnableICache();
AT91F_EnableDCache();
AT91F_LockITLB(0x10000000);
AT91F_LockICache(0x10020000, 0x3E00);
//========================== 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,0x07f00000,0x00000000,RW_NCNB); //bank0
MMU_SetMTT(0x08000000,0x0ff00000,0x08000000,RW_NCNB); //bank1
MMU_SetMTT(0x10000000,0x17f00000,0x10000000,RW_NCNB); //bank2
MMU_SetMTT(0x18000000,0x1ff00000,0x18000000,RW_NCNB); //bank3
MMU_SetMTT(0x20000000,0x27f00000,0x20000000,RW_NCNB); //bank4
MMU_SetMTT(0x28000000,0x2ff00000,0x28000000,RW_NCNB); //bank5
MMU_SetMTT(0x30000000,0x30f00000,0x30000000,RW_NCNB); //bank6-1
MMU_SetMTT(0x31000000,0x33e00000,0x31000000,RW_NCNB); //bank6-2
MMU_SetMTT(0x33f00000,0x33f00000,0x33f00000,RW_NCNB); //bank6-3
MMU_SetMTT(0x38000000,0x3ff00000,0x38000000,RW_NCNB); //bank7
MMU_SetMTT(0x40000000,0x4ff00000,0x40000000,RW_NCNB);//nCS3
MMU_SetMTT(0x50000000,0x8ff00000,0x50000000,RW_NCNB);//nCS3
MMU_SetMTT(0x90000000,0xeff00000,0x90000000,RW_FAULT);//not used
MMU_SetMTT(0xf0000000,0xfff00000,0xf0000000,RW_NCNB);//SFR
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)
{
U32 *pTT;
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);
for(i=0;i<=nSec;i++) *pTT++=
(i<<20)|
(1 << 10) | // Access in supervisor mode
(15 << 5) | // Domain
1 << 4 |
0x2;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -