微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > IO端口和IO内存的区别及分别使用的函数接口

IO端口和IO内存的区别及分别使用的函数接口

时间:11-23 来源:互联网 点击:

注意,I/O端口在重新映射前必须使用request_region分配所需的I/O端口。

3、ARM体系的I/O操作接口

s3c24x0处理器使用的是I/O内存,也就是说:s3c24x0处理器使用统一编址方式,I/O寄存器和内存使用的是单一地址空间,并且读写I/O寄存器和读写内存的指令是相同的。所以推荐使用I/O内存的相关指令和函数。但这并不表示I/O端口的指令在s3c24x0中不可用。如果你注意过s3c24x0关于I/O方面的内核源码,你就会发现:其实I/O端口的指令只是一个外壳,内部还是使用和I/O内存一样的代码。

下面是ARM体系原始的I/O操作函数。其实后面I/O端口和I/O内存操作函数,只是对这些函数进行再封装。从这里也可以看出为什么我们不推荐直接使用I/O端口和I/O内存地址指针,而是要求使用专门的I/O操作函数——专门的I/O操作函数会检查地址指针是否有效是否为IO地址(通过__iomem或__chk_io_ptr)

#include

/*
* Generic IO read/write. These perform native-endian accesses. Note
* that some architectures will want to re-define __raw_{read,write}w.
*/
externvoid__raw_writesb(void__iomem*addr,constvoid*data,intbytelen);
externvoid__raw_writesw(void__iomem*addr,constvoid*data,intwordlen);
externvoid__raw_writesl(void__iomem*addr,constvoid*data,intlonglen);
externvoid__raw_readsb(constvoid__iomem*addr,void*data,intbytelen);
externvoid__raw_readsw(constvoid__iomem*addr,void*data,intwordlen);
externvoid__raw_readsl(constvoid__iomem*addr,void*data,intlonglen);
#define__raw_writeb(v,a)(__chk_io_ptr(a),*(volatileunsignedchar__force*)(a)=(v))
#define__raw_writew(v,a)(__chk_io_ptr(a),*(volatileunsignedshort__force*)(a)=(v))
#define__raw_writel(v,a)(__chk_io_ptr(a),*(volatileunsignedint__force*)(a)=(v))
#define__raw_readb(a)(__chk_io_ptr(a),*(volatileunsignedchar__force*)(a))
#define__raw_readw(a)(__chk_io_ptr(a),*(volatileunsignedshort__force*)(a))
#define__raw_readl(a)(__chk_io_ptr(a),*(volatileunsignedint__force*)(a))

关于__force和__iomem

#include

/* __force表示所定义的变量类型是可以做强制类型转换的 */
#define__force __attribute__((force))
/* __iomem是用来修饰一个变量的,这个变量必须是非解引用(no dereference)的,即这个变量地址必须是有效的,而且变量所在的地址空间必须是2,即设备地址映射空间。0表示normal space,即普通地址空间,对内核代码来说,当然就是内核空间地址了。1表示用户地址空间,2表示是设备地址映射空间 */
#define__iomem __attribute__((noderef,address_space(2)))

I/O端口

#include

#defineoutb(v,p)__raw_writeb(v,__io(p))
#defineoutw(v,p)__raw_writew((__force __u16)
cpu_to_le16(v),__io(p))
#defineoutl(v,p)__raw_writel((__force __u32)
cpu_to_le32(v),__io(p))
#defineinb(p)({__u8 __v=__raw_readb(__io(p));__v;})
#defineinw(p)({__u16 __v=le16_to_cpu((__force __le16)
__raw_readw(__io(p)));__v;})
#defineinl(p)({__u32 __v=le32_to_cpu((__force __le32)
__raw_readl(__io(p)));__v;})
#defineoutsb(p,d,l)__raw_writesb(__io(p),d,l)
#defineoutsw(p,d,l)__raw_writesw(__io(p),d,l)
#defineoutsl(p,d,l)__raw_writesl(__io(p),d,l)
#defineinsb(p,d,l)__raw_readsb(__io(p),d,l)
#defineinsw(p,d,l)__raw_readsw(__io(p),d,l)
#defineinsl(p,d,l)__raw_readsl(__io(p),d,l)

I/O内存

#include

#defineioread8(p)({unsignedint__v=__raw_readb(p);__v;})
#defineioread16(p)({unsignedint__v=le16_to_cpu((__force __le16)__raw_readw(p));__v;})
#defineioread32(p)({unsignedint__v=le32_to_cpu((__force __le32)__raw_readl(p));__v;})
#defineiowrite8(v,p)__raw_writeb(v,p)
#defineiowrite16(v,p)__raw_writew((__force __u16)cpu_to_le16(v),p)
#defineiowrite32(v,p)__raw_writel((__force __u32)cpu_to_le32(v),p)
#defineioread8_rep(p,d,c)__raw_readsb(p,d,c)
#defineioread16_rep(p,d,c)__raw_readsw(p,d,c)
#defineioread32_rep(p,d,c)__raw_readsl(p,d,c)
#defineiowrite8_rep(p,s,c)__raw_writesb(p,s,c)
#defineiowrite16_rep(p,s,c)__raw_writesw(p,s,c)
#defineiowrite32_rep(p,s,c)__raw_writesl(p,s,c)

注意:

1)、所有的读写指令(I/O操作函数)所赋的地址必须都是虚拟地址,

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top