S3C2410下寄存器地址虚实映射的实现
S3C2410下寄存器地址虚实映射的实现
我们知道在我们的驱动里面一般操作的寄存器的地址都是虚拟地址, 然而一般在cpu的datasheet里描述的寄存器的地址都是物理地址, 那linux内核是如何把我们驱动中指定操作的虚拟地址转换成正真可寻址并操作的物理地址的呢? 这篇文档以s3c2410为例, 将详细的描述这么一个实现流程。通过这篇文章,将能够很好了解的虚实映射的过程。(本篇文章并非本人原著,只是整理以提供给大家交流学习。分析的不错)
S3C2410使用的是arm920T的核,它支持MMU,正因为这样它才可以进行虚拟地址到物理地址的转换。而诸如使用arm7核的CPU一般都无法进行类似的转换, 就在于它没有MMU,所以它上面能跑的操作系统也是去掉了MMU功能后的linux如uClinux, 关于MMU的原理可参考相关文档。
我们先来看文件Map.h
include\asm-arm\arch-s3c2410\Map.h:
#ifndef __ASSEMBLY__
#define S3C2410_ADDR(x) ((void __iomem __force *)0xF0000000 + (x))
#else
#define S3C2410_ADDR(x) (0xF0000000 + (x))
#endif
#define S3C2400_ADDR(x) S3C2410_ADDR(x)
/* interrupt controller is the first thing we put in, to make
* the assembly code for the irq detection easier
*/
#define S3C24XX_VA_IRQ S3C2410_ADDR(0x00000000)
#define S3C2400_PA_IRQ (0x14400000)
#define S3C2410_PA_IRQ (0x4A000000)
#define S3C24XX_SZ_IRQ SZ_1M
/* memory controller registers */
#define S3C24XX_VA_MEMCTRL S3C2410_ADDR(0x00100000)
#define S3C2400_PA_MEMCTRL (0x14000000)
#define S3C2410_PA_MEMCTRL (0x48000000)
#define S3C24XX_SZ_MEMCTRL SZ_1M
……
我们可以看到IRQ的寄存器虚拟地址定义为0xF0000000, 而物理地址为0x4A000000(这可从2410的datasheet上查到), memory控制器的寄存器虚拟地址定义为0xF0000000 + 0x00100000的地址处,物理地址为0x48000000, 其他如lcd 等寄存器都在这里定义了虚拟地址,当然这里仅仅是定义而已, 还没有和物理地址达成映射的联系。 我们接着看。
我们来看2410的machine_desc结构:
arch\arm\mach-s3c2410\Mach-smdk2410.c:
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
/* Maintainer: Jonas Dietsche */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = smdk2410_map_io,
.init_irq = s3c24xx_init_irq,
.init_machine = smdk2410_init,
.timer = &s3c24xx_timer,
MACHINE_END
这里定义了一个描述2410开发板的结构, 其中的map_io, init_irq, init_machine都会在系统跑起来的时候被调用, 我们这里要看的是smdk2410_map_io, 这个函数完成后我们的虚拟地址和物理地址的映射关系就完成了。
|
评论暂时关闭