物理地址转换为虚拟地址(静态)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

物理地址转换为虚拟地址(静态)

说明:

参考/Column/Column225.htm

物理地址可以静态地转换为虚拟地址,因为静态所以必须编译进内核。因此如需变动,必须更改内核代码,重新编译内核。

内核提供在系统启动时通过map_desc结构体静态创建I/O资源到内核地址空间的线性映射表。

程序员可以自己定义该I/O内存资源映射后虚拟地址。

创建好静态映射表后,在内核驱动访问I/O资源是无需ioremap动态映射,可以直接通过静态映射后的I/O虚拟地址访问。

静态映射表主要通过struct map_desc描述,主要有3个,分别是s3c_iodesc,s3c6410_iodesc,smdk6410_iodesc。

map_desc定义在文件arch/arm/include/asm/mach/map.h中,如下:

1 struct map_desc {

2 unsigned long virtual;

3 unsigned long pfn;

4 unsigned long length;

5 unsigned int type;

6 };

s3c_iodesc在文件arch/arm/plat-s3c64xx/cpu.c中定义,如下:

1 static struct map_desc s3c_iodesc[] __initdata = {

2 {

3 .virtual = (unsigned long)S3C_VA_SYS,

4 .pfn = __phys_to_pfn(S3C64XX_PA_SYSCON),

5 .length = SZ_4K,

6 .type = MT_DEVICE,

7 }, {

8 .virtual = (unsigned long)(S3C_VA_UART + UART_OFFS),

9 .pfn = __phys_to_pfn(S3C_PA_UART),

10 .length = SZ_4K,

11 .type = MT_DEVICE,

12 }, {

13 .virtual = (unsigned long)S3C_VA_VIC0,

14 .pfn = __phys_to_pfn(S3C64XX_PA_VIC0),

15 .length = SZ_16K,

16 .type = MT_DEVICE,

17 }, {

18 .virtual = (unsigned long)S3C_VA_VIC1,

19 .pfn = __phys_to_pfn(S3C64XX_PA_VIC1),

20 .length = SZ_16K,

21 .type = MT_DEVICE,

22 }, {

23 .virtual = (unsigned long)S3C_VA_TIMER,

24 .pfn = __phys_to_pfn(S3C_PA_TIMER),

25 .length = SZ_16K,

26 .type = MT_DEVICE,

27 }, {

28 .virtual = (unsigned long)S3C64XX_VA_GPIO,

29 .pfn = __phys_to_pfn(S3C64XX_PA_GPIO),

30 .length = SZ_4K,

31 .type = MT_DEVICE,

32 },

33 };

s3c6410_iodesc在文件arch/arm/mach-s3c6410/cpu.c中定义,如下:

1 static struct map_desc s3c6410_iodesc[] __initdata = {

2 IODESC_ENT(LCD),

3 IODESC_ENT(SROMC),

4 IODESC_ENT(HOSTIFB),

5 IODESC_ENT(OTG),

6 IODESC_ENT(OTGSFR),

7 };

smdk6410_iodesc在文件arch/arm/mach-s3c6410/mach-smdk6410.c中定义,如下:

1 struct map_desc smdk6410_iodesc[] = {

2 {

3 .virtual = (u32)S3C64XX_VA_DM9000,

4 .pfn = __phys_to_pfn(S3C64XX_PA_DM9000),

5 .length = S3C64XX_SZ_DM9000,

6 .type = MT_DEVICE,

7 },

8 };

我们若要添加新的静态映射,一般通过在smdk6410_iodesc结构体最后添加一项实现。

例如:把LED对应地址0x7F008820,按页对齐方式,映射一页。如下:

1 struct map_desc smdk6410_iodesc[] = {

2 {

3 .virtual = (u32)S3C64XX_VA_DM9000,

4 .pfn = __phys_to_pfn(S3C64XX_PA_DM9000),

5 .length = S3C64XX_SZ_DM9000,

6 .type = MT_DEVICE,

7 },

8 {

9 .virtual = (u32)0xEEEEE000,

10 .pfn = __phys_to_pfn(0x7F008000),

11 .length = SZ_4K,

12 .type = MT_DEVICE,

13 },

14 };

然后重新编译内核,并在开发板上使用新编出来的内核,测试一下程序。

程序一:测试IO静态映射,如上面所示。

创建文件夹/nfsroot/kern/2012-04-25/01/。

创建文件/nfsroot/kern/2012-04-25/01/test.c,内容如下:

1 #include

2 #include

3 #include

4

5 MODULE_LICENSE("GPL");

6

7 // see arch/arm/mach-s3c6410/mach-smdk6410.c ==> smdk6410_iodesc

8 static void *v_base = (void *)0xEEEEE000;

9 static void *v_conf;

10 static void *v_data;

11

12 static int __init test_init(void)

13 {

14 v_conf = v_base + 0x820;

15 v_data = v_base + 0x824;

16

17 iowrite32(0x1111, v_conf);

18 iowrite32(0x0, v_data);

19

20 return 0;

21 }

22

23 static void __exit test_exit(void)

相关文档
最新文档