A good memory is not as good as a bad pen. In order to facilitate the code review and code reuse in the future, here is the S3C2440 MMU code library I wrote. I used the friendly MINI2440 development board and the development environment was RealView MDK 4.22.
The source code structure is simple and clear. The original project download address: click to open the link
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");
}
Setting up the 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 initialization:
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();
}
It should be noted that if S3C2440.s is used directly, calling the above code in C code will cause an Undefine exception. This is because before entering main(), the startup code has set the processor mode to USER mode, and the CP15 processor cannot be operated in USER mode, so an exception occurs. If you want to call the above embedded assembly normally in C, you need to comment out the code in the startup code S3C2440.s that sets the processor mode to USER mode, and run it directly in SVC mode, and it will execute normally, as follows:
; 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
Or you can insert the following assembly directly after the Clock setting code in S3C2440.s without changing the processor mode, and it will work just the same:
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #0xc0000000
mcr p15, 0, r0, c1, c0, 0
Previous article:S3C2440 UART driver code template (RealView MDK)
Next article:S3C2440 LCD driver code template (RealView MDK)
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- Several problems found by using ATE to test GD32F450 (GD32 engineers can answer them if they see any)
- In AD, if the circle on the surface of the circuit board is not painted with green paint, should a solid circle or a ring be drawn on the TOPSOLDER layer?
- AD19 installation package always reports errors
- Tektronix offers free trials for more than 100 advanced application functions!
- Research on A-type digital flaw detection system based on FPGA.pdf
- Phase loss detection of three-phase three-wire circuit
- What is the packaging of integrated circuits? What are the common types of packaging? What are their respective characteristics?
- GaN tube selection
- I downloaded a source code from the Internet. I don't know what software it was developed with. The file type is shown in the picture. Please help me take a look.
- How to choose MOS tube for low power motor