好记心不如烂笔头,为方便以后查看代码及代码重复利用,这里贴出自己写的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
时间: 2024-10-12 19:22:31