驱动中直接访问IO口?

narwal 2011-04-11 07:17:25
今天看到一段代码,十分不解。
背景:整个代码是电视内的操作系统,基于linux。这一段代码是电视plane(就是一般LCD电视底部那个VOL+、VOL-、CH+、CH-、POWER等等)的驱动。基本原理是通过ADC读取电压值来判断哪个键按下了。以下是读取ADC口的代码:****表示不好公开东东

UINT32 *****ReadServoADCChannelValue(UINT32 u4Channel)
{
UINT32 u4Val, u4Ret;

// support 2 styles of servo adc numbering: 0 ~ 4 and 400 ~ 404
if(u4Channel >= ADIN0)
{
u4Channel -= ADIN0;
}
// Maximum is 8 channel.
VERIFY(u4Channel < TOTAL_SERVOADC_NUM);
... ...

#if defined(*****) || defined(*****)
u4Val = IO32ReadFld(PDWNC_SRVCFG1, FLD_SRVCH_EN);
... ...

IO32ReadFld的定义如下:

#define IO32ReadFld(reg32,fld) \
(((Fld_ac(fld)>=AC_FULLB0)&&(Fld_ac(fld)<=AC_FULLB3))?u1IO32Read1B((reg32)+(Fld_ac(fld)-AC_FULLB0))\
... ...省略

u1IO32Read1B定义如下(关键来了):

#define u1IO32Read1B(reg32) (*(volatile UINT8 *)(reg32))

最初那个PDWNC_SRVCFG1定义为:
#define PDWNC_SRVCFG1 (IO_VIRT+0x28304)
难道内核中可以直接地址访问?极度不解,但是事实告诉我这段代码没问题,因为电视plane跑的很好。那个0x28304难道就起到一个remap作用?其原理是什么?
...全文
172 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiongga 2011-04-15
  • 打赏
  • 举报
回复
1.在Linux的系统的底层有个驱动负责进行寄存器以及GPIO的Remap,在这里将寄存器映射到内存空间(注意是空间,不是实际的内存,也就是说,OS知道访问这部分内存空间的时候,就是读写寄存器)。
2.具体的GPIO和内存空间地址之间的映射关系由硬件决定,参照CPU手册和硬件的电路。(少部分可以配置的参照系统初始化部分的具体设定)
3.驱动不是一层的,也是有层次的,上层的驱动使用下层的驱动去访问具体的硬件。对于上层的驱动,访问具体寄存器或者通过寄存器访问GPIO,直接读写内存空间的地址就可以。
narwal 2011-04-15
  • 打赏
  • 举报
回复
求解答
求解答啊
求解答啊啊
求解答啊啊啊啊
求解答啊啊啊啊啊啊
求解答啊啊啊啊啊啊啊啊
求解答啊啊啊啊啊啊啊啊啊啊
narwal 2011-04-15
  • 打赏
  • 举报
回复
可能有点少见多怪了
但是其中原理还是不太明白:
1. 为什么要用加固定值的方法?这种方法可靠吗?这个固定值确实“固定”的吗?
2. 这个值是怎么算出来的?
jack850219 2011-04-13
  • 打赏
  • 举报
回复
这样是可以的,因为虚拟地址和物理地址的转化其实就是物理地址加上一个差值,现在linux驱动中一般都用ioremap够转换,但还是有很多人甚至一些官方驱动还都是通过加上一定的差值来转换成虚拟地址,你可以多看一些linux内核中的驱动,就会发现了
narwal 2011-04-12
  • 打赏
  • 举报
回复
再补充一下:系统核心是arm11
linux内核使用的是虚拟内存地址,怎么可以直接访问某个地址呢?
“访问IO内存之前,需要使用ioremap函数将设备寄存器所处的物理地址映射到虚拟地址。”
我在操作另一块板子的led时也是查看芯片的datasheet,找到相应寄存器地址,再ioremap,之后访问。
曹大夯 2011-04-11
  • 打赏
  • 举报
回复
要是不好理解,可以考虑将对应的数值打印出来,看看实际的数值是多少。然后,对应芯片的Datasheet,看寄存器和端口定义就应该明白了。
svtanto 2011-04-11
  • 打赏
  • 举报
回复
没什么奇怪的,Windows操作系统是把IO端口映射为内存中的地址的,所谓的通过两个寄存器访问,一个是命令寄存器,一个是数据寄存器,两个寄存器本身就是内存地址。估计Linux系统也是同样的吧。我没看过资料

21,595

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧