IO端口映射

来源:互联网 发布:淘宝美人库 编辑:程序博客网 时间:2024/06/18 06:05
linux下不可以对设备的寄存器直接访问,必须使设备的物理地址映射到内存中的虚拟地址,这样访问内存中的虚拟地址就等于访问设备的物理地址。起初在分析TX2440_adc.c中不明白 “static void __iomem *base_addr;”这个定义,主要是不清楚__iomem这个关键字的作用,后来在网上搜集到了一些关于它的资料:__iomem是2.6.9中加入的特性。是用来个表示指向一个I/O的内存空间。主要是为了driver的通用性考虑。由于不同的CPU体系结构对I/O空间的表示可能不同。当使用__iomem时,compiler会忽略对变量的检查(因为用的是void __iomem)。其目的就是说明base_addr是内存中的虚拟地址。后来在后文发现“base_addr=ioremap(S3C2410_PA_ADC,0x20);”这个语句,终于找到了关于base_addr的语句,但是又不清楚ioremap函数的作用,在网上搜了搜关于它的资料:ioremap的功能是将一个IO地址空间映射到内核的虚拟地址空间上去,返回值就是虚拟地址。  物理地址和虚拟地址的转换,就是将S3C2410_PA_ADC物理地址转换为base_addr 的地址,映射的个数为0x20。 S3C2410_PA_ADC 为物理地址0x58000000(map.h中定义) 。base_addr 虚拟地址,应该是有系统分配的,调用ioremap()既能分配到。通过这个语句就把设备的物理地址0x58000000映射到了内存中的虚拟地址,并把这个虚拟地址就是base_addr,这样以后我们就可以访问物理地址了。其中在文件的开头有:

#define ADCCON      (*(volatile unsigned long *)(base_addr + S3C2410_ADCCON)) //ADC control
#define ADCTSC      (*(volatile unsigned long *)(base_addr + S3C2410_ADCTSC)) //ADC touch screen control
#define ADCDLY      (*(volatile unsigned long *)(base_addr + S3C2410_ADCDLY)) //ADC start or Interval Delay
#define ADCDAT0     (*(volatile unsigned long *)(base_addr + S3C2410_ADCDAT0)) //ADC conversion data 0
#define ADCDAT1     (*(volatile unsigned long *)(base_addr + S3C2410_ADCDAT1)) //ADC conversion data 1

这样以后我们就可以直接对ADCCON、ADCTSC等直接操作了,如:ADCCON |= 0x1; 就是对物理地址的操作

转载自:http://blog.sina.com.cn/s/blog_a4f25cac01014zi4.html