S3C2440之MMU驱动代码模板(RealView MDK)

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

S3C2440之MMU驱动代码模板(RealView MDK)的相关文章

S3C2440之UART驱动代码模板(RealView MDK)

好记心不如烂笔头,为方便以后查看代码及代码重复利用,这里贴出S3C2440 UART驱动代码.使用友善MINI2440开发板,开发环境为RealView MDK 4.22.需要注意的是,本代码中,对GPIO的初始化放在了s3c2440.s中完成,采用keil自带的html方式进行配置. 该源码结构简单明了,原始工程下载地址:点击打开链接 UART控制器初始化: void Uart_Init(void) { #define rULCON0 (*(volatile unsigned int*)0x5

S3C2440之Camera驱动代码模板(RealView MDK)

好记心不如烂笔头,为方便以后查看代码及代码重复利用,这里贴出S3C2440 Camera驱动代码.使用友善MINI2440开发板,开发环境为RealView MDK 4.22. 原始工程下载地址:点击打开链接 最初,本人在网上下载了许多mini2440 camera驱动的代码,但结果都不尽人意,因为这些代码看起来都比较晦涩难懂,都是直接对寄存器进行位与位或操作,且有的代码排版布局很乱,对初学者来说难度较大.由于本人接触了STM32开发后,觉得STM32的库函数给初学者提供了很大帮助,仅仅通过函数

S3C2440之LCD驱动代码模板(RealView MDK)

好记心不如烂笔头,为方便以后查看代码及代码重复利用,这里贴出S3C2440 LCD控制初始化代码.使用友善MINI2440开发板,LCD为320*240,开发环境为RealView MDK 4.22. 该源码结构简单明了,原始工程下载地址:点击打开链接 寄存器宏定义: #define rGPCCON (*(volatile unsigned long *)0x56000020) #define rGPCUP (*(volatile unsigned long *)0x56000028) #def

在KEIL realview MDK下为单一C文件生成.LIB文件

纠结了一天,竟然没有一个网页完整的说清楚的这个问题,莫非太简单了大家不屑于说?看大多数说的都是简单地将整个工程转换成.LIB,在Project->Options for Target->Output下,选择Create Library,就可以了. 不过这样生成的lib文件巨大,我现在编译的工程最后生成的lib有2.6MB. 后来还是从KEIL官网英文资料中找到灵感(http://www.keil.com/support/docs/2610.htm): 1.右键点击工程,假设为a,选Add Gr

S3C2440之MMU

转自:http://blog.chinaunix.net/uid-23193900-id-3187782.html 1.MMU简介 MMU(Memory Management Unit),内存管理单元,主要职责:将虚拟地址映射为物理地址,提供硬件机制的内存访问权限检查. 2.基本概念 虚拟地址(Virtual Address,VA),修改后的虚拟地址(Modified VA),物理地址(Phisical Address) VA是CPU使用的地址,MVA是MMU.Caches使用的,PA是内存设备

s3c2440液晶屏驱动 (非内核自带) linux-4.1.24

对于,不想逐一检查内核自带驱动,想自己编写驱动. 1,make menuconfig 去掉 编译到内核,改为 M 编译为 模块(因为要用到里面的3个.ko 驱动) Device Drivers --->    Graphics support --->        Support for frame buffer devices --->            <M> S3C2410 LCD framebuffer support 2,make uImage &&a

S3C2440 UART串口驱动

++++++++++++++++++++++++++++++++++++++++++ 本文转载自mr_raptor的专栏,感谢mr_raptor大神. http://blog.csdn.net/mr_raptor/article/details/6556133 ++++++++++++++++++++++++++++++++++++++++++ 通用异步接收器和发送器(Universal Asynchronous Receiver and Transmitter)简称UART.通常是嵌入式设备中

s3c2440液晶屏驱动新内核 linux-4.1.24

自带有一部分驱动的配置信息,只要修改这部分就能支援 不同的液晶屏 - /arch/arm/mach-s3c24xx/mach-smdk2440.c 另一部分在 /drivers/video/fbdev/s3c2410fb.c 先打开调试功能,这样内核在启动的时候,就可以输出这些信息,或者使用 dmesg 查看到这些信息.当然,你配置内核 make menuconfig 也可以打开,但是太麻烦了,不如这样. 1 #define CONFIG_FB_S3C2410_DEBUG 2 #define d

SPI在linux3.14.78 FS_S5PC100(Cortex A8)和S3C2440上驱动移植(deep dive)

由于工作的原因,对SPI的理解最为深刻,也和SPI最有感情了,之前工作都是基于OSEK操作系统上进行实现,也在US/OS3上实现过SPI驱动的实现和测试,但是都是基于基本的寄存器操作,没有一个系统软件架构的思想,感觉linux SPI驱动很强大,水很深,废话少说,SPI总线上有两类设备:一类是主机端,通常作为SOC系统的一个子模块出现,比如很多嵌入式MPU中都常常包含SPI模块.一类是从机被控端,例如一些SPI接口的Flash.传感器等等.主机端是SPI总线的控制者,通过使用SPI协议主动发起S