{$cluname}

科伟奇论坛 » Powerpc技术论坛 » 对IO寄存器访问问题


‹‹上一主题 | 下一主题›› 查看 7208
发表一个新帖子 发表回复

标题 对IO寄存器访问问题 在百度搜索本主题 [ 搜 ] [ 打印 ] [ 推荐 ] [收藏帖子] [ 收藏到新浪VIVI] [ 订阅 ]

frodo (附小一年级)
楼主   [点击复制本网址] [ 字体: ] [ 编辑 ] [ 报告 ] [评分]
Rank:1
Rank:1
UID 21
帖子 7
精华 1 
积分 26 点
金币 43 枚
魅力 18 度
注册 2009年11月26日
对IO寄存器访问问题

遇到问题:PowerPC8349开发板,带有两个网卡,VSC8201和VSC7385,现在想通过改变7385的内部寄存器数值来开启一些功能,但不知道如何去读写7385的寄存器。在mpc8349e-mitx board configuration file——MPC8349ITX.h里有定义:
#define CFG_VSC7385_BASE      0xF8000000   /* start of VSC7385   */
下图是8349的内存分布图,其中可以看到,7385是挂在Local Bus上的,地址空间为0xF8000000—0xF801FFFF,和程序中定义的起始地址一样。
 
 
 
 
下面是一个访问8349的IMMRBAR寄存器的程序,以模块形式加载
#include <linux/init.h>
#include <linux/module.h>
#include <asm/mpc83xx.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
       printk(KERN_alert "Hello, world\n");
       printk(KERN_alert "IMMR virtual address: %X\n", VIRT_IMMRBAR);
       printk(KERN_alert "IMMRBAR: %08lX\n", *(unsigned long*)(VIRT_IMMRBAR + 0x05008));
       return 0;
}
static void hello_exit(void)
{
       printk(KERN_alert "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
这个程序加载之后,可以成功的读出IMMRBAR寄存器中的数值,也可以直接从绝对地址中读取,但把地址改成7385的0xF8000000之后,再次进行读取就会出现段错误,而且从其它大部分地址中读取都会出现段错误。
在网上参阅了一些资料后发现,驱动程序访问的是IO空间,与一般我们说的内存空间是不同的。外设的IO空间地址是系统启动后才知道,CPU通常并没有为这些已知的外设I/O内存资源的物理地址预定义虚拟地址范围,所以驱动程序并不能直接通过物理地址访问I/O内存资源,而必须将它们映射到核心虚地址空间内然后才能根据映射所得到的核心虚地址范围,通过访内指令访问这些I/O内存资源。
 
下面这一段讲了一下Linux内存空间的划分,不是很懂,还需要再仔细理解一下。(转自 http://tech.sina.com.cn/s/2006-10-27/15181207636.shtml
对于提供了MMU(存储管理器,辅助操作系统进行内存管理,提供虚实地址转换等硬件支持)的处理器而言,Linux提供了复杂的存储管理系统,使得进程所能访问的内存达到4GB。
进程的4GB内存空间被人为的分为两个部分--用户空间与内核空间。用户空间地址分布从0到3GB(PAGE_OFFSET,在0x86中它等于0xC0000000),3GB到4GB为内核空间,如下图:

  内核空间中,从3G到vmalloc_start这段地址是物理内存映射区域(该区域中包含了内核镜像、物理页框表mem_map等等),比如我们使用的VMware虚拟系统内存是160M,那么3G~3G+160M这片内存就应该映射物理内存。在物理内存映射区之后,就是vmalloc区域。对于160M的系统而言,vmalloc_start位置应在3G+160M附近(在物理内存映射区与vmalloc_start期间还存在一个8M的gap来防止跃界),vmalloc_end的位置接近4G(最后位置系统会保留一片128k大小的区域用于专用页面映射),如下图:
 一般来说,在系统运行时,外设的I/O内存资源的物理地址是已知的,由硬件的设计决定。但是CPU通常并没有为这些已知的外设I/O内存资源的物理地址预定义虚拟地址范围,驱动程序并不能直接通过物理地址访问I/O内存资源,而必须将它们映射到核心虚地址空间内(通过页表),然后才能根据映射所得到的核心虚地址范围,通过访内指令访问这些I/O内存资源。Linux在io.h头文件中声明了函数ioremap(),用来将I/O内存资源的物理地址映射到核心虚地址空间(3GB-4GB)中,原型如下:
void * ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
  iounmap函数用于取消ioremap()所做的映射,原型如下:
void iounmap(void * addr);
这两个函数都是实现在mm/ioremap.c文件中。
在将I/O内存资源的物理地址映射成核心虚地址后,理论上讲我们就可以象读写RAM那样直接读写I/O内存资源了。为了保证驱动程序的跨平台的可移植性,我们应该使用Linux中特定的函数来访问I/O内存资源,而不应该通过指向核心虚地址的指针来访问。如在x86平台上,读写I/O的函数如下所示:
#define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
#define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
#define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
#define memset_io(a,b,c) memset(__io_virt(a),(b),(c))
#define memcpy_fromio(a,b,c) memcpy((a),__io_virt(b),(c))
#define memcpy_toio(a,b,c) memcpy(__io_virt(a),(b),(c))
 
最后,我们要特别强调驱动程序中mmap函数的实现方法。用mmap映射一个设备,意味着使用户空间的一段地址关联到设备内存上,这使得只要程序在分配的地址范围内进行读取或者写入,实际上就是对设备的访问。
最后解决办法:用ioremap函数对物理地址进行转换,对转换后得到的地址进行读写操作都是可以的,代码如下:
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
#define CFG_VSC7385_BASE 0xF8000000
static int hello_init(void)
{
       void * mypointer = ioremap(0xF8000000,128*1024); //地址转换
        printk(KERN_alert "Hello, world\n");
        printk(KERN_alert" CHIPID:%08lX\n",*(unsignedlong*)(mypointer+0X1C060));
        iounmap(mypointer);    //取消转换
        return 0;
}
static void hello_exit(void)
{
        printk(KERN_alert "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
疑问:是不是只有对3G(即0xC0000000)之后的地址才能用这种地址转换的方式来访问呢?

按此在新窗口浏览图片
附件尺寸:10.9 KB
 




此用户离线!
共计在线时长60分钟2009/11/26 22:22:23
[ 资料 ] [ 短信 ] [ 好友 ] [ 文集 ] [ 引用 ] [ 回复 ] 点击返回顶部

joy (版主)
第2楼 [ 字体: ] [ 编辑 ] [ 报告 ] [评分]
Rank:16Rank:16Rank:16Rank:16Rank:16
UID 34
帖子 10
积分 26 点
金币 47 枚
魅力 19 度
注册 2009年11月30日
回复:对IO寄存器访问问题
表情图标EM1



此用户离线!
共计在线时长100分钟2009/11/30 12:21:08
[ 资料 ] [ 短信 ] [ 好友 ] [ 文集 ] [ 引用 ] [ 回复 ] 点击返回顶部

nihao (附小一年级)
第3楼 [ 字体: ] [ 编辑 ] [ 报告 ] [评分]
Rank:1
Rank:1
UID 229
帖子 22
积分 22 点
金币 67 枚
魅力 23 度
注册 2018年9月11日
回复:对IO寄存器访问问题



此用户离线!
共计在线时长0分钟2018/9/11 16:17:22
[ 资料 ] [ 短信 ] [ 好友 ] [ 文集 ] [ 引用 ] [ 回复 ] 点击返回顶部

« 首页1 »2/共1页


查看积分策略说明快速回复你的内容
快捷回复标题 (选填) 快捷插入表情图标
验 证 码  点击获取验证码
快捷回复内容

自动复制

Powered by TEAM 2.0.5 Release - ACC © 2005 Team5 Studio All rights reserved