ARM MMU
好记性不如烂笔头,为方便以后查看代码及代码重复利用,这里贴出自己写的S3C2440 MMU代码库。使用友善MINI2440开发板,开发环境为RealView MDK 4.22。
Register 0, ID code register:
-
unsigned int MMU_ReadID(void)
-
{
-
unsigned int id;
-
__asm("mrc p15, 0, id, c0, c0, 0");
-
return id;
-
}
Register 0, cache type register:
-
unsigned int MMU_ReadCacheType(void)
-
{
-
unsigned int type;
-
__asm("mrc p15, 0, type, c0, c0, 1");
-
return type;
-
}
Register 1, control register:
-
void MMU_EnterFastBusMode(void)
-
{
-
unsigned int r0;
-
__asm{
-
mrc p15, 0, r0, c1, c0, 0
-
bic r0, r0, #(3<<30)
-
mcr p15, 0, r0, c1, c0, 0
-
}
-
}
-
-
void MMU_EnterSyncMode(void)
-
{
-
unsigned int r0;
-
__asm{
-
mrc p15, 0, r0, c1, c0, 0
-
bic r0, r0, #(1<<31)
-
orr r0, r0, #(1<<30)
-
mcr p15, 0, r0, c1, c0, 0
-
}
-
}
-
-
void MMU_EnterAsyncMode(void)
-
{
-
unsigned int r0;
-
__asm{
-
mrc p15, 0, r0, c1, c0, 0
-
orr r0, r0, #(11<<30)
-
mcr p15, 0, r0, c1, c0, 0
-
}
-
}
-
-
-
void MMU_EnableICache(void)
-
{
-
unsigned int r0;
-
__asm{
-
mrc p15, 0, r0, c1, c0, 0
-
orr r0, r0, #(1<<12)
-
mcr p15, 0, r0, c1, c0, 0
-
}
-
}
-
-
-
void MMU_DisableICache(void)
-
{
-
unsigned int r0;
-
__asm{
-
mrc p15, 0, r0, c1, c0, 0
-
bic r0, r0, #(1<<12)
-
mcr p15, 0, r0, c1, c0, 0
-
}
-
}
-
-
-
void MMU_EnableDCache(void)
-
{
-
unsigned int r0;
-
__asm{
-
mrc p15, 0, r0, c1, c0, 0
-
orr r0, r0, #(1<<2)
-
mcr p15, 0, r0, c1, c0, 0
-
}
-
}
-
-
-
void MMU_DisableDCache(void)
-
{
-
unsigned int r0;
-
__asm{
-
mrc p15, 0, r0, c1, c0, 0
-
bic r0, r0, #(1<<2)
-
mcr p15, 0, r0, c1, c0, 0
-
}
-
}
-
-
void MMU_EnableAlignFault(void)
-
{
-
unsigned int r0;
-
__asm{
-
mrc p15, 0, r0, c1, c0, 0
-
orr r0, r0, #(1<<1)
-
mcr p15, 0, r0, c1, c0, 0
-
}
-
}
-
-
-
void MMU_DisableAlignFault(void)
-
{
-
unsigned int r0;
-
__asm{
-
mrc p15, 0, r0, c1, c0, 0
-
bic r0, r0, #(1<<1)
-
mcr p15, 0, r0, c1, c0, 0
-
}
-
}
-
-
void MMU_Enable(void)
-
{
-
unsigned int r0;
-
__asm{
-
mrc p15, 0, r0, c1, c0, 0
-
orr r0, r0, #1
-
mcr p15, 0, r0, c1, c0, 0
-
}
-
}
-
-
-
void MMU_Disable(void)
-
{
-
unsigned int r0;
-
__asm{
-
mrc p15, 0, r0, c1, c0, 0
-
bic r0, r0, #1
-
mcr p15, 0, r0, c1, c0, 0
-
}
-
}
Register 2, translation table base (TTB) register:
-
void MMU_SetTTB(void)
-
{
-
unsigned int r0 = (unsigned int)TTB;
-
__asm("mcr p15, 0, r0, c2, c0, 0");
-
}
Register 3, domain access control register:
-
void MMU_SetDomain(unsigned int domain)
-
{
-
__asm("mcr p15, 0, domain, c3, c0, 0");
-
}
Register 7, cache operations register:
-
void MMU_InvalidICacheDCache(void)
-
{
-
unsigned int r0 = 0;
-
-
__asm("mcr p15, 0, r0, c7, c7, 0");
-
}
-
-
void MMU_InvalidICache(void)
-
{
-
unsigned int r0 = 0;
-
-
__asm("mcr p15, 0, r0, c7, c5, 0");
-
}
-
-
void MMU_InvalidICacheSingleEntry(unsigned int MVA)
-
{
-
__asm("mcr p15, 0, MVA, c7, c5, 1");
-
}
-
-
void MMU_PrefechICacheLine(unsigned int MVA)
-
{
-
__asm("mcr p15, 0, MVA, c7, c13, 1");
-
}
-
-
void MMU_InvalidDCache(void)
-
{
-
unsigned int r0 = 0;
-
-
__asm("mcr p15, 0, r0, c7, c6, 0");
-
}
-
-
void MMU_InvalidDCacheSingleEntry(unsigned int MVA)
-
{
-
__asm("mcr p15, 0, MVA, c7, c6, 1");
-
}
-
-
void MMU_CleanDCacheSingleEntry(unsigned int MVA)
-
{
-
__asm("mcr p15, 0, MVA, c7, c10, 1");
-
}
-
-
void MMU_CleanInvalidDCacheEntry(unsigned int MVA)
-
{
-
__asm("mcr p15, 0, MVA, c7, c14, 1");
-
}
-
-
void MMU_CleanDCacheSingleEntry2(unsigned int index)
-
{
-
__asm("mcr p15, 0, index, c7, c10, 2");
-
}
-
-
void MMU_CleanInvalidDCacheEntry2(unsigned int index)
-
{
-
__asm("mcr p15, 0, index, c7, c14, 2");
-
}
-
-
void MMU_DrainWriteBuffer(void)
-
{
-
unsigned int r0 = 0;
-
-
__asm("mcr p15, 0, r0, c7, c10, 4");
-
}
-
-
void MMU_WaitForInterrupt(void)
-
{
-
unsigned int r0 = 0;
-
-
__asm("mcr p15, 0, r0, c7, c0, 4");
-
}
Register 8, TLB operations register:
-
void MMU_InvalidAllTLB(void)
-
{
-
unsigned int r0 = 0;
-
-
__asm("mcr p15, 0, r0, c8, c7, 0");
-
}
-
-
void MMU_InvalidITLB(void)
-
{
-
unsigned int r0 = 0;
-
-
__asm("mcr p15, 0, r0, c8, c5, 0");
-
}
-
-
void MMU_InvalidITLBSingleEntry(unsigned int MVA)
-
{
-
__asm("mcr p15, 0, MVA, c8, c5, 1");
-
}
-
-
void MMU_InvalidDTLB(void)
-
{
-
unsigned int r0 = 0;
-
-
__asm("mcr p15, 0, r0, c8, c6, 0");
-
}
-
-
void MMU_InvalidDTLBSingleEntry(unsigned int MVA)
-
{
-
__asm("mcr p15, 0, MVA, c8, c6, 1");
-
}
Register 9, cache lockdown register:
-
unsigned int MMU_ReadDCacheLockdownBase(void)
-
{
-
unsigned int r0;
-
-
__asm("mrc p15, 0, r0, c9, c0, 0");
-
r0 >>= 26;
-
-
return r0;
-
}
-
-
void MMU_WriteDCacheLockdownBase(unsigned int index)
-
{
-
index <<= 26;
-
__asm("mcr p15, 0, index, c9, c0, 0");
-
}
-
-
-
unsigned int MMU_ReadICacheLockdownBase(void)
-
{
-
unsigned int r0;
-
-
__asm("mrc p15, 0, r0, c9, c0, 1");
-
r0 >>= 26;
-
-
return r0;
-
}
-
-
void MMU_WriteICacheLockdownBase(unsigned int index)
-
{
-
index <<= 26;
-
__asm("mcr p15, 0, index, c9, c0, 1");
-
}
Register 13, FCSE PID register:
-
unsigned int MMU_ReadPID(void)
-
{
-
unsigned int pid;
-
-
__asm("mrc p15, 0, pid, c13, c0, 0");
-
-
return (pid >> 25);
-
}
-
-
void MMU_WritePID(unsigned int pid)
-
{
-
pid <<= 25;
-
__asm("mcr p15, 0, pid, c13, c0, 0");
-
}
设置Memory Translation Table:
-
void MMU_SetMTT(unsigned int vStart, unsigned int vEnd, unsigned int pStart, unsigned int attr)
-
{
-
unsigned int vaddr, paddr;
-
-
vaddr = vStart;
-
paddr = pStart;
-
while(vaddr != (vEnd + 1))
-
{
-
TTB[vaddr >> 20] = (paddr & 0xFFF00000) | attr;
-
vaddr += 0x100000;
-
paddr += 0x100000;
-
}
-
}
MMU初始化:
-
void MMU_Init(void)
-
{
-
MMU_DisableICache();
-
MMU_DisableDCache();
-
-
MMU_SetTTB();
-
MMU_SetDomain(0xFFFFFFFF);
-
MMU_InvalidAllTLB();
-
MMU_EnableAlignFault();
-
-
MMU_SetMTT(0x00000000, 0x001FFFFF, 0x00000000, RW_CB);
-
MMU_SetMTT(0x30000000, 0x33FFFFFF, 0x30000000, RW_CB);
-
MMU_SetMTT(0x40000000, 0x4FFFFFFF, 0x40000000, RW_NCNB);
-
MMU_SetMTT(0x50000000, 0x5FFFFFFF, 0x50000000, RW_NCNB);
-
-
MMU_EnableICache();
-
MMU_EnableDCache();
-
MMU_Enable();
-
}
在本代码中需要注意的是,如果直接使用S3C2440.s的话,在C代码中调用上述代码会导致Undefine异常。因为进入main()之前,启动代码已经将处理器模式设置为USER模式了,而在USER模式下是无法操作CP15处理器的,所以产生异常。如果要在C中正常调用上述嵌入汇编,则需要将启动代码S3C2440.s中处理器模式设置为USER模式的那段代码注释掉,直接以SVC模式运行,就能正常执行,如下:
-
; Enter Supervisor Mode and set its Stack Pointer
-
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
-
MOV SP, R0
-
SUB R0, R0, #SVC_Stack_Size
-
-
; Enter User Mode and set its Stack Pointer
-
; MSR CPSR_c, #Mode_USR
-
; MOV SP, R0
-
; SUB SL, SP, #USR_Stack_Size
-
-
; Enter User Mode and set its Stack Pointer
-
; MSR CPSR_c, #Mode_USR
-
; IF :DEF:__MICROLIB
-
-
; EXPORT __initial_sp
-
-
; ELSE
-
-
; MOV SP, R0
-
; SUB SL, SP, #USR_Stack_Size
-
-
; ENDIF
或者不修改处理器模式,而直接将以下汇编插入到S3C2440.s中Clock设置代码的后面,一样能运行:
-
mrc p15, 0, r0, c1, c0, 0
-
orr r0, r0, #0xc0000000
-
mcr p15, 0, r0, c1, c0, 0
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律