当前位置: 技术问答>linux和unix
_IOWR
来源: 互联网 发布时间:2016-05-11
本文导语: _IOWR在驱动中是不是用来对映射到内存中的地址上的寄存器进行读写的?还是干什么的? 这个东西到底是做什么的?有什么作用,为什么这么做? 在linux中是如何访问cpu上的寄存器的? | 参...
_IOWR在驱动中是不是用来对映射到内存中的地址上的寄存器进行读写的?还是干什么的?
这个东西到底是做什么的?有什么作用,为什么这么做?
在linux中是如何访问cpu上的寄存器的?
这个东西到底是做什么的?有什么作用,为什么这么做?
在linux中是如何访问cpu上的寄存器的?
|
|
1. _IOWR()实际就是定义一个常数,用来作为ioctl()的cmd;
2. 我不知道你说的访问CPU的内部寄存器(比如arm的r0,r1,r2等),还是CPU外设的配置空间? 如果是前者,直接用汇编指令访问就可以了。比如 "add r0, r0, #1", "mov r1, 0xF"等。如果是后者,在开启MMU之前,你可以直接用物理地址访问。在开启MMU之后,你需要先将物理地址映射为虚拟地址,然后用虚拟地址访问。还是绝个简单的例子,比如某一个外设的寄存器物理地址为: regaddr = 0x0200000,要读出/写入的值为value(unsigned int类型);那么:
在开启MMU之前:
读:
value = *(volatile unsigned int*)regaddr;
写:
*(volatile unsigned int*)regaddr = value;
在开启MMU之后:
需要先用ioremap来做映射,如下
unsigned int virt_regaddr = 0;
virt_regaddr = ioremap (regaddr, sizeof (unsigned int));
读:
value = *(volatile unsigned int *)virt_regaddr;
写:
*(volatile unsigned int*)virt_regaddr = value;
当然,如果不使用了,记得用iounmap()来回收资源。
PS: 如果某些物理内存段在kernel初始化过程中已经为了做好了这种映射,那么直接拿映射后的虚拟地址来使用就可以了。
2. 我不知道你说的访问CPU的内部寄存器(比如arm的r0,r1,r2等),还是CPU外设的配置空间? 如果是前者,直接用汇编指令访问就可以了。比如 "add r0, r0, #1", "mov r1, 0xF"等。如果是后者,在开启MMU之前,你可以直接用物理地址访问。在开启MMU之后,你需要先将物理地址映射为虚拟地址,然后用虚拟地址访问。还是绝个简单的例子,比如某一个外设的寄存器物理地址为: regaddr = 0x0200000,要读出/写入的值为value(unsigned int类型);那么:
在开启MMU之前:
读:
value = *(volatile unsigned int*)regaddr;
写:
*(volatile unsigned int*)regaddr = value;
在开启MMU之后:
需要先用ioremap来做映射,如下
unsigned int virt_regaddr = 0;
virt_regaddr = ioremap (regaddr, sizeof (unsigned int));
读:
value = *(volatile unsigned int *)virt_regaddr;
写:
*(volatile unsigned int*)virt_regaddr = value;
当然,如果不使用了,记得用iounmap()来回收资源。
PS: 如果某些物理内存段在kernel初始化过程中已经为了做好了这种映射,那么直接拿映射后的虚拟地址来使用就可以了。
|
命令码的组织是有一些讲究的,因为我们一定要做到命令和设备是一一对应的,这样才不会将正确的命令发给错误的设备,或者是把错误的命令发给正确的设备,或者是把错误的命令发给错误的设备。这些错误都会导致不可预料的事情发生,而当程序员发现了这些奇怪的事情的时候,再来调试程序查找错误,那将是非常困难的事情。所以在Linux核心中是这样定义一个命令码的:
网管u家u.bitscn@com
____________________________________
| 设备类型 | 序列号 | 方向 |数据尺寸|
|----------|--------|------|--------|
| 8 bit | 8 bit |2 bit |8~14 bit|
|----------|--------|------|--------|
这样一来,一个命令就变成了一个整数形式的命令码。但是命令码非常的不直观,所以Linux Kernel中提供了一些宏,这些宏可根据便于理解的字符串生成命令码,或者是从命令码得到一些用户可以理解的字符串以标明这个命令对应的设备类型、设备序列号、数据传送方向和数据传输尺寸。这里确实要说一说,cmd参数在用户程序端由一些宏根据设备类型、序列号、传送方向、数据尺寸等生成,这个整数通过系统调用传递到内核中的驱动程序,再由驱动程序使用解码宏从这个整数中得到设备的类型、序列号、传送方向、数据尺寸等信息,然后通过switch{case}结构进行相应的操作。
网管u家u.bitscn@com
____________________________________
| 设备类型 | 序列号 | 方向 |数据尺寸|
|----------|--------|------|--------|
| 8 bit | 8 bit |2 bit |8~14 bit|
|----------|--------|------|--------|
这样一来,一个命令就变成了一个整数形式的命令码。但是命令码非常的不直观,所以Linux Kernel中提供了一些宏,这些宏可根据便于理解的字符串生成命令码,或者是从命令码得到一些用户可以理解的字符串以标明这个命令对应的设备类型、设备序列号、数据传送方向和数据传输尺寸。这里确实要说一说,cmd参数在用户程序端由一些宏根据设备类型、序列号、传送方向、数据尺寸等生成,这个整数通过系统调用传递到内核中的驱动程序,再由驱动程序使用解码宏从这个整数中得到设备的类型、序列号、传送方向、数据尺寸等信息,然后通过switch{case}结构进行相应的操作。
|
_IOXX是驱动IOCTL命令号的宏转换定义,用于对命令进行分类,防止不同类驱动程序具有相同命令号,导至误打开驱动程序而驱动程序功能调用被误操作.
您可能感兴趣的文章:
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。