免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3626 | 回复: 6
打印 上一主题 下一主题

请教,一个AT91SAM9260的实地址虚地址映射问题[ [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-07-29 13:05 |只看该作者 |倒序浏览
10可用积分
请教大家
两个与 LINUX 地址映射有关的问题,
问题 1:

我们所用的 AT91SAM9260 的寄存器的实际地址是 0xFFF7 8000 .. 0xFFFF FFFF(实地址,Datasheet中), 我看 Linux 的程序中把这个地址映射到 0xFEF7 8000 .. 0xFF00 0000(虚拟地址)。
这样的话 Datasheet上的寄存器地址和程序中使用的地址(虚拟地址)就有个差值,我操作寄存器的时候,得自己去换算一下。
这里, 就有个问题呢,我想的是,要是直接把实地址的 0xFFF7 8000 也映射到 虚地址的 0xFFF7 8000 ,两个值都一样的话,这样我程序里操作寄存器就不用去换算了,就可以直接使用 Datasheet 上所写的地址了。
那他们为什么要映射到 0xFEF7 8000 呢??有什么特殊的原因吗??

程序中的寄存器映射:                                            我的想法:

             差值 0x0100 0000                                     差值 0x 0
                     /     \                                                 /       \
                    /        \                                              /          \
       实地址   /           \   虚地址                       实地址  /             \  虚地址
0xFFF7 8000  __       __ 0xFEF7 8000      0xFFF7 8000 __        __ 0xFFF7 8000
                      |      |                                                      |      |
                      |=>  |                                                      |=> |
                      |      |                                                      |     |
0xFFFF FFFF  __|       |__ 0xFF00,0000      0xFFFF FFFF __|      |__ 0xFFFF FFFF

刚刚想到一个原因,好像在哪里看到过,最顶部的一部分地址 0x xxxx xxxx ... 0xFFFF FFFF linux 内核要使用,是这个原因吗??  

问题 2:
另一个问题是,我现在所知道的一个说法是,在内核中才能操作寄存器地址。 在应用程序中不能直接读取寄存器的值(如某个IO口的电平)。
我的理解是,这个权限的控制,无非是在 MMU 初始化时,对这些寄存器的地址的权限做了限制,那如果在 MMU 初始话时,对这些寄存器地址的权限做适当的修改,比如不限制权限的话,那我在应用程序中就可以直接操作这些寄存器,这样不是会很方便吗?? 比如我想读一个 IO 的电平,就不用去修改驱动了。 可以这样吗???

谢谢了先。。

论坛徽章:
0
2 [报告]
发表于 2009-07-30 10:51 |只看该作者
LZ可能以前都是编写无操作系统的ARM程序的吧。
像第二个问题,IO的操作最好交给驱动来做,因为我们的程序是多进程的,同一个外设可以被多个进程使用,如何解决冲突,这都是驱动的职责;再者,我们要有分层的概念,应用程序最好不要直接操作外设寄存器,如果真要使用,也是映设使用的,实际地址是不会操作的。我看到很多没有MMU的像uclinux,这种应用程序有些为了图方便,有直接读写寄存器的情况。

论坛徽章:
0
3 [报告]
发表于 2009-07-30 12:42 |只看该作者
谢谢指点,嘿嘿,是的,之前都是在 Nucleus+ ARM 上做程序的,最近才在 ARM9+Linux上做东西的。。

继续请教第一个问题哈。

论坛徽章:
0
4 [报告]
发表于 2009-07-30 20:51 |只看该作者

回复 #1 ermaerma 的帖子

1。如果你对MMU比较熟悉的话,问题本来很简单。
MMU(Memory Management Unit)负责将CPU发出的虚拟地址转换为实际访问设备(即最后放到地址总线上的)的物理地址(就是你文中的实地址)。
AT91SAM9260中的ARM芯片(ARM926?)应该自带MMU,一般linux内核启动时会使能MMU,也就是说,此后CPU访问任何CPU外资源(DDRAM,外设等)都是使用虚拟地址,由MMU负责将这个虚拟地址转换为实际访问设备的物理地址。
那么知道设备的物理地址,可不可以直接在程序中使用进行直接访问?
回答是不能!如果是内核层程序(如insmodable内核驱动)则内核会dump core,显示非法访问,因为所使用的物理地址在MMU页表中没有对应项。
所以要访问外围设备,在linux下,一般首先都要使用ioremap函数进行映射,其完成的功能即创建相应的MMU页表项,返回这个页表项对应的虚拟地址,此后程序中对外设的所有访问都必须要使用该虚拟地址。
至于物理地址具体被映射到哪个虚拟地址,更进一步,对应一个具体的物理地址,是不是每次调用
ioremap都被映射到相同的虚拟地址,这个就要研究ioremap函数的实现算法,一般而言,我们对此不关心。
而你所涉及的问题根本不能成为问题,所谓差值,那么应该是你长期在无MMU映射机制下编程所造成的。如果你习惯了,并且对MMU机制比较了解,对虚拟,物理地址也明白,那么也就不会产生以上的问题。
至于说如何去消除差值,完全没有必要,而且比较麻烦,姑且说成是无法做到!
(当然你可以修改linux内核,禁止MMU,就可以实现你以前的编程环境了。)
对于临近0xFFFF FFFF 的高端地址,印象中linux将PC bios(640K-1M的区域)映射到了这段区域(不是很确定,自己去查)。

2。ARM没有intel对内存和外设区域进行区分的那一套,所有外设资源都在一个域中,外设寄存器也是作为内存空间访问的,不存在什么外设寄存器无法访问的问题。问题的症结在于在linux应用层要对外设进行操作,一般都要经过底层驱动完成。
你既然都可以去修改MMU页表项了,为何不能在驱动上小做文章?

论坛徽章:
0
5 [报告]
发表于 2009-08-03 13:37 |只看该作者
感谢回复,看来还是基础的理论没学到,得补补呢,不过看啥书呢??

论坛徽章:
0
6 [报告]
发表于 2009-08-04 11:17 |只看该作者
那是不是意味着以前的不带MMU 的uClinux下可以直接炒作硬件的寄存器呢?

论坛徽章:
0
7 [报告]
发表于 2009-08-15 17:14 |只看该作者

回复 #6 kyzlin 的帖子

没有MMU,不会有地址映射了,可以直接操作内存单元
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP