物理地址转换为虚拟地址(静态)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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)