Chinaunix

标题: 求助:驱动程序如何操作寄存器的那 比如知道它的地址了 [打印本页]

作者: ruiyunzhon    时间: 2009-10-23 21:22
标题: 求助:驱动程序如何操作寄存器的那 比如知道它的地址了
rtrtrtrt
作者: llzzccc    时间: 2009-10-23 22:26
都已经知道地址了,直接那指针往上写东西,那不就是改变寄存器的内容了吗?不也就是控制寄存器了吗?
作者: ruiyunzhon    时间: 2009-10-24 09:34
谢谢啊 比如地址为0x12345678
我想赋值为0x12
就是*(0x12345678)=0x12  ???

那么下面这句什么意思那
#define MYREG   _reg( 0x12345678 )

[ 本帖最后由 ruiyunzhon 于 2009-10-24 09:40 编辑 ]
作者: emmoblin    时间: 2009-10-24 12:16
操作一般都是用inb,outb指令,高级一点的有readb,writeb之类的函数。
作者: zyr-linux    时间: 2009-10-24 15:56
翻手册,看寄存器类型io还是memory;

看见io、port用in,out;
看见memory,address用read,write;

对地址,通常取得的是物理地址,还要加个PAGE_OFFSET之类转换为虚拟地址。
某些情况下取得的地址后面几位是标志位,记得清0。

PS:想知道寄存器具体如何操作,方法1:啃手册,方法2:啃手册、方法三:啃手册

[ 本帖最后由 zyr-linux 于 2009-10-24 16:08 编辑 ]
作者: ruiyunzhon    时间: 2009-10-24 16:19
标题: 回复 #4 emmoblin 的帖子
linux 下驱动程序 好像没有outb吧
如何操作内部专用寄存器(比如完成ad转换的)
作者: epegasus    时间: 2009-10-24 18:34
标题: 回复 #5 zyr-linux 的帖子
同意这个。
作者: ruiyunzhon    时间: 2009-10-25 16:06
标题: 回复 #5 zyr-linux 的帖子
谢谢你 但是我说的是linux下驱动程序 应该没有所谓的read 之类的
但是你说的物理地址 转虚拟地址 我还是深受启发的
不过还是不懂 怎么转换的那
是不是与板子的物理连接有关 还是其他的?
作者: zyr-linux    时间: 2009-10-25 20:18
各种设备上的寄存器,要么作为IO端口操作(in、out);要么映射到虚拟地址空间中,和内存一样操作(read、write)。

你的Linux内核里面没有下面这些接口?
inb、outb;
readb,writeb、readw,writew、readl、writel、readq,writeq。

物理地址、线性地址、虚拟地址这些,还是找本深入理解Linux翻吧。
作者: magicboatrocket    时间: 2009-10-26 22:48
如果是在arm linux下,先ioremap 返回一个虚拟地址, 再用readb, writeb等楼上提到的函数读写。
作者: llzzccc    时间: 2009-10-27 00:00
标题: 回复 #3 ruiyunzhon 的帖子
抱歉,我说的不清楚,
应该是先映射,然后再操作,前面的已经说了,用inb、outb,readb,writeb、readw,writew、readl、writel、readq,writeq。API 操作。
有一点,我以前是通过把寄存器映射为结构,然后对结构的不同成员操作的。那些就是指针的操作了。现在突然间有点迷糊了,请高人指教。
#define MYREG   _reg( 0x12345678 ) 这个好像是编译的时候对这个地址的读写有些不同。哎,一接触更具体的,就迷糊,还是没学会啊。
作者: 奇门遁甲-lu    时间: 2009-10-27 16:56
标题: re
既然不想写驱动,
那就直接 ope    /dev/mem/
然后mmap,读写;

[ 本帖最后由 奇门遁甲-lu 于 2009-10-27 16:57 编辑 ]
作者: epegasus    时间: 2009-10-27 17:19
标题: 回复 #11 llzzccc 的帖子
乱用映射这个词了.

ia32处理器工作在保护模式下,对内存的操作是对虚拟内存的寻址,所以直接按指针操作就行了.
但是这个过程是需要先经过MMU,变换成虚拟地址.然后变成对物理地址的访问.这里把物理地址映射成虚拟地址.
这里虚拟地址通常还是指在内核空间中,还有在用户空间的方法,要先把物理地址直接映射到用户空间去.

在没有mmu的处理器比如8051等,就没这么多讲究.直接找地址读写就行了.
作者: LightInDark_pan    时间: 2009-10-27 18:18
在驱动里可以直接读写寄存器的,一般来说是设置个基地址,然后使用偏移来读写。
[code]
#defien baseAddress 0xF89999000 //看手册
int read8(int offset)
{
    return *((char*)(baseAddress+offset));
}
void write8(int offset ,int value)
{
    *(char*)(baseAddress+offset) = value;
}
[code]

同样实现16位的与32位的, 基本就可以操作了。注意大小端的操作, 基本就没啥事了。

还有一种方式就是 mmap,可以在驱动中实现将一块物理地址映射成逻辑地址,就可以在用户态操作了。

以上2种方式 我都玩过,应该可行的。
作者: zhiwood    时间: 2009-10-27 21:53
设备的寄存器多种多样, 有的可以直接写, 有的只能间接写. 比如pci总线上的寄存器有三种种地址空间, configuration空间, io 空间,和 memory 空间. 物理地址和长度都是写在pci设备的configuration space 中. configuration space的东西需要通过间接的方式读取, 地址是bus:device:function的格式. pc机上通过in,out读取0xcf8 0xcfCf来访问. io空间的就要通过in, out, 加上device定义的偏移量. memory空间也是一样, 在配置空间里有关于它的基地址和长度. 基地址不是不变的, 而是由bios或者操作系统动态分配的, 所以手册里一般不会给出一个绝对的物理地址. 在实际访问的时候, 一般操作系统都为你作好了这些配置和地址的映射, 应该查找看看官方的获得这些参数的办法. 毕竟操作系统要同一管理这些资源. 如果没有的话, 一般io地址不需要做虚拟地址到物理地址的转换. 而mem的地址就必需要做转换. 所谓memory空间, 就是一类地址, 可以让普通的cpu指令, 如mov, add引起pci总线的访问, 从而读取寄存器. 这些指令一般都是要经过地址映射的, 原因就是虚地址的使用. linux的ioremap, 或者windows的MmMapIoSpace专门干这种事. 如果直接拿个物理地址访问的话, 要么pci返回错误的value要么cpu throw access violation. 有的时候还有一种logical address的, 它站在physical address和虚地址之间, 它的一个优点是一些古老的设备, 只能在低地址dma的, 现在可以dma到那遥远的高地址了内存了.
作者: llzzccc    时间: 2009-10-27 22:31
标题: 回复 #13 epegasus 的帖子
学习了,用词要严谨,抱歉
作者: xxxx486    时间: 2009-10-28 09:19
标题: 开源的。
读读源代码就知道了。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2