当前位置: 首页 > 科技观察

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

时间:2023-03-14 20:36:00 科技观察

ARM统一寻址内存空间和IO空间,所以通过读写SFR来控制硬件就变成了读写对应的SFR地址控制硬件。这部分地址也称为I/O内存。在x86中,I/O地址和内存地址是分开编址的,这样的IO地址称为I/O端口。本文只讨论IO内存访问。IO内存访问流程我们知道,为了管理最重要的系统资源,让物理地址对进程透明,Linux使用了内存映射机制,即如果一个进程要访问一个物理内存地址(eg.it映射到一个虚拟地址IO内存申请/返回Linux提供了一组函数来申请和释放IO内存的范围,这两个API在访问IO内存时不是必须的,但是推荐使用,他们可以检查请求的资源是否request_mem_region()宏函数request_mem_region()宏函数从内存中申请n个内存地址,如果可用,则申请成功并标记为已使用,其他驱动申请失败,进程返回资源从first开始,len的长度,name表示设备名称,成功返回非NULL,失败返回NULL。/***request_mem_region-createanewbusyresourceregion*@start:resourcestartaddress*@n:resourceregionsize*@name:reservingcaller'sIDstring*/structresource*request_mem_region(resource_size_tstart,resource_size_tn,constchar*name)release_mem_region()宏函数,顾名思义就是申请request_mem_region的IO内存资源返回给内核,以便其他进程也可以访问IO内存。/***release_mem_region-releaseapreservedreservedresourceregion*@start:resourcestartaddress*@n:resourceregionsize*/voidrelease_mem_region(resource_size_tstart,resource_size_tn,constchar*name)IO资源申请的IO内存映射/解映射,下一步是进行物理地址到虚拟地址映射。内核提供的API如下staticinlinevoid__iomem*ioremap(unsignedlongport,unsignedlongsize)staticinlinevoidiounmap(volatilevoid__iomem*addr)IO内存访问APIARM的SFR是32bit的。通过ioremap之后,我们其实可以通过强制类型转换直接读取得到的虚拟地址,但是这种方式不够安全,一不小心就会读取到错误的位置。为此,内核还提供了读写IO内存的标准API,不仅让代码更加安全,也提高了可读性。读IOunsignedintioread8(void*addr)unsignedintioread16(void*addr)unsignedintioread32(void*addr)写IOvoidiowrite8(u8val,void*addr)voidiowrite16(u8val,void*addr)voidiowrite32(u8val,void*addr)读一串IO内存voidioread8_rep(void*addr,void*buf,unsignedlonglen)voidioread16_rep(void*addr,void*buf,unsignedlonglen)voidioread32_rep(void*addr,void*buf,unsignedlonglen)写一串IO内存voidiowrite8_rep(void*addr,constvoid*buf,unsignedlonglen)voidiowrite16_rep(void*addr,constvoid*buf,unsignedlonglen)voidiowrite32_rep(void*addr,constvoid*buf,unsignedlonglen)复制IO内存voidmemcpy_fromio(void*dest,void*source,unsignedlonglen)voidmemcpy_toio(void*dest,void*source,unsignedlonglen)设置IO内存voidmemset_io(void*addr,u8value,unsignedintlen)