良许Linux教程网 干货合集 Linux驱动中的I/O内存访问技术:原理与方法

Linux驱动中的I/O内存访问技术:原理与方法

I/O内存是Linux系统中一种特殊的内存,它用来映射外设的寄存器,使得驱动程序可以通过读写内存来控制外设。I/O内存的访问是Linux驱动开发中最常见的操作之一,它涉及到物理地址和虚拟地址,端口映射和内存映射,字节访问和字访问等概念。在本文中,我们将介绍Linux驱动中的I/O内存访问技术,并举例说明它们的使用方法和注意事项。

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

IO内存访问流程

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

img
img

IO内存申请/归还

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

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

/**
 * request_mem_region - create a new busy resource region
 * @start: resource start address
 * @n: resource region size
 * @name: reserving caller's ID string
 */

struct resource * request_mem_region(resource_size_t start, resource_size_t n,const char *name)

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

/**
 * release_mem_region - release a previously reserved resource region
 * @start: resource start address
 * @n: resource region size
 */
void release_mem_region(resource_size_t start, resource_size_t n,const char *name)

IO内存映射/去映射

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

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

IO内存访问API

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

读IO

unsigned int ioread8(void *addr)
unsigned int ioread16(void *addr)
unsigned int ioread32(void *addr)

写IO

void iowrite8(u8 val,void *addr)
void iowrite16(u8 val,void *addr)
void iowrite32(u8 val,void *addr)

读一串IO内存

void ioread8_rep(void *addr,void *buf,unsigned long len)
void ioread16_rep(void *addr,void *buf,unsigned long len)
void ioread32_rep(void *addr,void *buf,unsigned long len)

写一串IO内存

void iowrite8_rep(void *addr,const void *buf,unsigned long len)
void iowrite16_rep(void *addr,const void *buf,unsigned long len)
void iowrite32_rep(void *addr,const void *buf,unsigned long len)

复制IO内存

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

设置IO内存

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

通过本文,我们了解了Linux驱动中的I/O内存访问技术,它们可以用来实现对外设寄存器的读写操作。我们应该根据实际需求选择合适的函数,并遵循一些基本原则,如先申请再映射,先释放再取消映射,使用正确的数据类型和大小等。I/O内存访问技术是Linux驱动开发中不可或缺的一部分,它可以实现对外设的控制和配置,也可以提升驱动程序的效率和兼容性。希望本文能够对你有所帮助和启发。

以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !

137e00002230ad9f26e78-265x300
本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部