ioremap映射的问题
来源:互联网 发布:双色球参选数据诈骗 编辑:程序博客网 时间:2024/05/16 09:37
ioremap 写驱动最常用的函数之一,但是对它始终一知半解,看了内核关于这部分的代码,功力不够也是一头雾水。本文通过实验的方法,了解 ioremap 到底干了些啥,本文献给那些看不懂内核源代码,还想知道 ioremap 能干些什么,干了些什么的同学。
实验方法:
点灯实验,LED接在GPB5~8,因此需要使用 gpbcon 配置,gpbdat 输出高低。
gpbcon 0x56000010
gpbdat 0x56000014
下面,尝试了各种 ioremap 的方法测试,点灯 关灯 是否正常,点灯正常代表寄存器访问没问题。
1、字节映射还是页映射?
gpbcon = (volatile unsigned long *)ioremap(0x56000010, 1);
gpbdat = gpbcon + 1;
测试结果,点灯正常,虽然只映射一个字节,但是 gpbcon、gpbdat 使用虚拟地址时可以访问到物理地址,因此是页映射。
2、同一页的 映射的物理地址之前的地址是否也映射了?
gpbdat = (volatile unsigned long *)ioremap(0x56000014, 1);
gpbcon = gpbdat - 1;
测试结果,点灯正常,虽然只映射了1个字节,但是之前的地址也可以访问到对应的物理地址,因此,该物理地址所在的页,全都都进行了映射。
3、同一页内,重复映射会怎样?
gpbcon = (volatile unsigned long *)ioremap(0x56000010, 1);
gpbdat = (volatile unsigned long *)ioremap(0x56000014, 1);
temp = (volatile unsigned long *)ioremap(0x56000014, 1);
printk("gpbcon: %x\n", gpbcon);
printk("gpbdat: %x\n", gpbdat);
printk(" temp: %x\n", temp);
输出:
gpbcon: c483c010
gpbdat: c4840014
temp: c4844014
测试结果:
程序依旧正常运行,但是输出的 gpbcon、gpbdat 虚拟地址不连续!即使是相同的物理地址 ioremap 得到的虚拟地址不相等。
4、那么,gpbcon + 1 也就是 c483c014 是不是也对应于 gpbdat的物理地址呢?
gpbcon = (volatile unsigned long *)ioremap(0x56000010, 1);
gpbdat = (volatile unsigned long *)ioremap(0x56000014, 1);
temp = (volatile unsigned long *)ioremap(0x56000014, 1);
printk("gpbcon: %x\n", gpbcon);
printk("gpbdat: %x\n", gpbdat);
printk(" temp: %x\n", temp);
gpbdat_temp = gpbcon + 1;
测试 虚拟地址gpbdat_temp 、gpbdat 是不是都能访问到 gpbdat 的物理地址。
输出:
gpbcon: c484a010
gpbdat: c484e014
temp: c4852014
测试结果:
1、神奇,程序正常运行,也就是说通过 虚拟地址 c484e014 或者(c484a010 + 4) 都能访问到 gpbdat 的物理地址!
因此,如果两个物理地址位于同一页,我们是没必要去两次ioremap的,1次就够了,而且两次会浪费掉一页虚拟空间。
2、 推理,我通过ioremap temp 得到的虚拟地址也可以访问到 gpbdat 的物理地址。
我通过ioremap temp 得到的虚拟地址 -4 也可以访问到 gpbcon 的物理地址。
5、重复映射了,如何iounmap ?
gpbcon = (volatile unsigned long *)ioremap(0x56000010, 1);
gpbdat = (volatile unsigned long *)ioremap(0x56000014, 1);
temp = (volatile unsigned long *)ioremap(0x56000014, 1);
printk("gpbcon: %x\n", gpbcon);
printk("gpbdat: %x\n", gpbdat);
printk(" temp: %x\n", temp);
iounmap(gpbcon);
iounmap(gpbdat);
iounmap(temp);
测试:程序正常,没有崩溃。
ioremap 可以有多个虚拟地址对应于一个物理地址,iounmap时相互不受影响。
猜测:iounmap(gpbcon + n);保证(gpbcon + n 与 gpbcon在同一页)应该也可以释放掉gpbcon,没有测试。
结论:
1、ioremap 按照页大小进行映射,而且是 整页 。
2、ioremap 允许对一个物理地址进行多次映射,而且分配的虚拟空间地址各不相同(多个虚拟地址对应于同一个物理地址)。而且,ioumap相互不影响。
曾经疑惑的那些问题:
1、我要是用一个寄存器,4个字节
ioremap(0x56000010, 1);
ioremap(0x56000010, 4);
都能用?显然,都能用页映射,该物理地址所在的页,已经全部被映射了。
2、两个驱动程序,都要用到同一个寄存器,两次ioremap/iounmap会不会冲突?
显然经过上边的实验,它们各自ioremap得到的虚拟地址不同,iounmap时只是把各地的虚拟地址释放了而已,相互不会产生影响。
实验方法:
点灯实验,LED接在GPB5~8,因此需要使用 gpbcon 配置,gpbdat 输出高低。
gpbcon 0x56000010
gpbdat 0x56000014
下面,尝试了各种 ioremap 的方法测试,点灯 关灯 是否正常,点灯正常代表寄存器访问没问题。
1、字节映射还是页映射?
gpbcon = (volatile unsigned long *)ioremap(0x56000010, 1);
gpbdat = gpbcon + 1;
测试结果,点灯正常,虽然只映射一个字节,但是 gpbcon、gpbdat 使用虚拟地址时可以访问到物理地址,因此是页映射。
2、同一页的 映射的物理地址之前的地址是否也映射了?
gpbdat = (volatile unsigned long *)ioremap(0x56000014, 1);
gpbcon = gpbdat - 1;
测试结果,点灯正常,虽然只映射了1个字节,但是之前的地址也可以访问到对应的物理地址,因此,该物理地址所在的页,全都都进行了映射。
3、同一页内,重复映射会怎样?
gpbcon = (volatile unsigned long *)ioremap(0x56000010, 1);
gpbdat = (volatile unsigned long *)ioremap(0x56000014, 1);
temp = (volatile unsigned long *)ioremap(0x56000014, 1);
printk("gpbcon: %x\n", gpbcon);
printk("gpbdat: %x\n", gpbdat);
printk(" temp: %x\n", temp);
输出:
gpbcon: c483c010
gpbdat: c4840014
temp: c4844014
测试结果:
程序依旧正常运行,但是输出的 gpbcon、gpbdat 虚拟地址不连续!即使是相同的物理地址 ioremap 得到的虚拟地址不相等。
4、那么,gpbcon + 1 也就是 c483c014 是不是也对应于 gpbdat的物理地址呢?
gpbcon = (volatile unsigned long *)ioremap(0x56000010, 1);
gpbdat = (volatile unsigned long *)ioremap(0x56000014, 1);
temp = (volatile unsigned long *)ioremap(0x56000014, 1);
printk("gpbcon: %x\n", gpbcon);
printk("gpbdat: %x\n", gpbdat);
printk(" temp: %x\n", temp);
gpbdat_temp = gpbcon + 1;
测试 虚拟地址gpbdat_temp 、gpbdat 是不是都能访问到 gpbdat 的物理地址。
输出:
gpbcon: c484a010
gpbdat: c484e014
temp: c4852014
测试结果:
1、神奇,程序正常运行,也就是说通过 虚拟地址 c484e014 或者(c484a010 + 4) 都能访问到 gpbdat 的物理地址!
因此,如果两个物理地址位于同一页,我们是没必要去两次ioremap的,1次就够了,而且两次会浪费掉一页虚拟空间。
2、 推理,我通过ioremap temp 得到的虚拟地址也可以访问到 gpbdat 的物理地址。
我通过ioremap temp 得到的虚拟地址 -4 也可以访问到 gpbcon 的物理地址。
5、重复映射了,如何iounmap ?
gpbcon = (volatile unsigned long *)ioremap(0x56000010, 1);
gpbdat = (volatile unsigned long *)ioremap(0x56000014, 1);
temp = (volatile unsigned long *)ioremap(0x56000014, 1);
printk("gpbcon: %x\n", gpbcon);
printk("gpbdat: %x\n", gpbdat);
printk(" temp: %x\n", temp);
iounmap(gpbcon);
iounmap(gpbdat);
iounmap(temp);
测试:程序正常,没有崩溃。
ioremap 可以有多个虚拟地址对应于一个物理地址,iounmap时相互不受影响。
猜测:iounmap(gpbcon + n);保证(gpbcon + n 与 gpbcon在同一页)应该也可以释放掉gpbcon,没有测试。
结论:
1、ioremap 按照页大小进行映射,而且是 整页 。
2、ioremap 允许对一个物理地址进行多次映射,而且分配的虚拟空间地址各不相同(多个虚拟地址对应于同一个物理地址)。而且,ioumap相互不影响。
曾经疑惑的那些问题:
1、我要是用一个寄存器,4个字节
ioremap(0x56000010, 1);
ioremap(0x56000010, 4);
都能用?显然,都能用页映射,该物理地址所在的页,已经全部被映射了。
2、两个驱动程序,都要用到同一个寄存器,两次ioremap/iounmap会不会冲突?
显然经过上边的实验,它们各自ioremap得到的虚拟地址不同,iounmap时只是把各地的虚拟地址释放了而已,相互不会产生影响。
0 0
- ioremap映射的问题
- Linux内核中ioremap映射的理解
- 函数 ioremap 物理地址到内核映射空间的映射函数
- 函数 ioremap 物理地址到内核映射空间的映射函数
- LED驱动----ioremap 映射
- [经典]Linux内核中ioremap映射的透彻理解
- Linux内核中ioremap映射的透彻理解
- Linux内核中ioremap映射的透彻理解
- [经典]Linux内核中ioremap映射的透彻理解
- [经典]Linux内核中ioremap映射的透彻理解
- [经典]Linux内核中ioremap映射的透彻理解
- [经典]Linux内核中ioremap映射的透彻理解
- Linux内核中ioremap映射的透彻理解
- [经典]Linux内核中ioremap映射的透彻理解
- [经典]Linux内核中ioremap映射的透彻理解
- Linux内核中ioremap映射的透彻理解
- 经典]Linux内核中ioremap映射的透彻理解 .
- [经典]Linux内核中ioremap映射的透彻理解
- Android基础:ExpandableListView
- 润乾报表统计图模态窗口传递单元格值
- HDU1532Drainage Ditches(网络流Ford-Fulkerson模板)
- iOS--打开第三方应用
- Arduino使用ESP8266通信的实践
- ioremap映射的问题
- python 高级特性
- hadoop中MapReduce多种join实现实例分析
- CSS3实战开发:手把手教大家折角效果实战开发
- Island Perimeter
- Java中的I/O流及利用I/O流实现文件复制功能
- SET NEWNAME FOR DATABASE TO恢复数据库
- [读书笔记]30 天自制操作系统 day2 汇编语言学习与Makefile入门
- 初入MVP框架