Linux驱动技术(二) _访问I/O内存

简介:

ARM是对内存空间和IO空间统一编址的,所以,通过读写SFR来控制硬件也就变成了通过读写相应的SFR地址来控制硬件。这部分地址也被称为I/O内存。x86中对I/O地址和内存地址是分开编址的,这样的IO地址被称为I/O端口。本文只讨论IO内存的访问。

IO内存访问流程

我们知道,为了管理最重要的系统资源并让物理地址对进程透明,Linux使用了内存映射机制,就是一个进程如果想访问一个物理内存地址(eg.SFR地址),那么首先就是将其映射成虚拟地址。  

IO内存访问流程

IO内存申请/归还

Linux提供一组函数用于申请和释放IO内存的范围,这两个API在访问IO内存的时候并不是必须的,但是建议使用,他们可以检查申请的资源是否可用,增加IO访问的安全性,如果可用则申请成功,并标志为已用,其他驱动想在这个进程归还资源前申请就会失败。

request_mem_region()宏函数向内存申请n个内存地址,这些地址从first开始,len长,name表示设备的名称,成功返回非NULL失败返回NULL。

 
 
  1. /** 
  2.  * request_mem_region - create a new busy resource region 
  3.  * @start: resource start address 
  4.  * @n: resource region size 
  5.  * @name: reserving caller's ID string 
  6.  */ 
  7.  
  8. struct resource * request_mem_region(resource_size_t start, resource_size_t n,const char *name 

release_mem_region()宏函数顾名思义就是将request_mem_region()申请的IO内存资源归还给内核以便其他进程也可以访问该IO内存。

 
 
  1. /** 
  2.  * release_mem_region - release a previously reserved resource region 
  3.  * @start: resource start address 
  4.  * @n: resource region size 
  5.  */ 
  6.  
  7. void release_mem_region(resource_size_t start, resource_size_t n,const char *name 

IO内存映射/去映射

申请了IO资源,接下来就是进行物理地址到虚拟地址的映射。内核提供的API如下

 
 
  1. static inline void __iomem *ioremap(unsigned long port, unsigned long size
 
 
  1. static inline void iounmap(volatile void __iomem *addr) 

IO内存访问API

ARM的SFR是32bit的,我们在经过了ioremap之后其实就可以直接通过强制类型转换来读取获取的虚拟地址,但是这种方法不够安全,一不小心就会读错位,为此,内核同样提供的标准的API来读写IO内存,不但代码的安全性更高,可读性也得到了改善。

读IO

 
 
  1. unsigned int ioread8(void *addr) 
  2. unsigned int ioread16(void *addr) 
  3. unsigned int ioread32(void *addr) 

写IO

 
 
  1. void iowrite8(u8 val,void *addr) 
  2. void iowrite16(u8 val,void *addr) 
  3. void iowrite32(u8 val,void *addr) 

读一串IO内存

 
 
  1. void ioread8_rep(void *addr,void *buf,unsigned long len) 
  2. void ioread16_rep(void *addr,void *buf,unsigned long len) 
  3. void ioread32_rep(void *addr,void *buf,unsigned long len) 

写一串IO内存

 
 
  1. void iowrite8_rep(void *addr,const void *buf,unsigned long len) 
  2. void iowrite16_rep(void *addr,const void *buf,unsigned long len) 
  3. void iowrite32_rep(void *addr,const void *buf,unsigned long len) 

复制IO内存

 
 
  1. void memcpy_fromio(void *dest,void *source,unsigned long len) 
  2. void memcpy_toio(void *dest,void *source,unsigned long len) 

设置IO内存

 
 
  1. void memset_io(void *addr,u8 value,unsigned int len)  





本文作者:佚名
来源:51CTO
目录
相关文章
|
3天前
|
消息中间件 算法 Linux
【Linux】详解如何利用共享内存实现进程间通信
【Linux】详解如何利用共享内存实现进程间通信
|
3天前
|
Java Linux Arthas
linux上如何排查JVM内存过高?
linux上如何排查JVM内存过高?
17 0
|
3天前
|
网络协议 Shell Linux
LabVIEW 在NI Linux实时设备上访问Shell
LabVIEW 在NI Linux实时设备上访问Shell
|
6天前
|
消息中间件 存储 Unix
【探索Linux】P.15(进程间通信 —— system V共享内存)
【探索Linux】P.15(进程间通信 —— system V共享内存)
17 0
|
6天前
|
Linux
linux驱动层输出dev_dbg打印信息
linux驱动层输出dev_dbg打印信息
11 0
|
6天前
|
关系型数据库 MySQL Linux
Linux 文件访问权限说明
Linux 文件访问权限说明
11 0
|
7天前
|
安全 Linux Python
Volatility3内存取证工具安装及入门在Linux下的安装教程
Volatility3内存取证工具安装及入门在Linux下的安装教程
Volatility3内存取证工具安装及入门在Linux下的安装教程
|
17天前
|
Linux
Linux rsyslog占用内存CPU过高解决办法
该文档描述了`rsyslog`占用内存过高的问题及其解决方案。
40 4
|
1月前
|
移动开发 运维 监控
掌握Linux运维利器:查看CPU和内存占用,轻松解决性能问题!
掌握Linux运维利器:查看CPU和内存占用,轻松解决性能问题!