Home  >  Article  >  System Tutorial  >  I/O memory access technology in Linux drivers: principles and methods

I/O memory access technology in Linux drivers: principles and methods

王林
王林forward
2024-02-11 12:10:031243browse

I/O memory is a special kind of memory in the Linux system. It is used to map the registers of peripherals so that the driver can control the peripherals by reading and writing memory. I/O memory access is one of the most common operations in Linux driver development. It involves concepts such as physical address and virtual address, port mapping and memory mapping, byte access and word access, etc. In this article, we will introduce I/O memory access technologies in Linux drivers and illustrate their usage and precautions with examples.

I/O memory access technology in Linux drivers: principles and methods

ARM addresses the memory space and IO space uniformly, so controlling the hardware by reading and writing SFR becomes controlling the hardware by reading and writing the corresponding SFR address. This part of the address is also called I/O memory. In x86, I/O addresses and memory addresses are addressed separately. Such IO addresses are called I/O ports. This article only discusses IO memory access

IO memory access process

We know that in order to manage the most important system resources and make the physical address transparent to the process, Linux uses a memory mapping mechanism. That is, if a process wants to access a physical memory address (eg. SFR address), then it must first Map to a virtual address.

I/O memory access technology in Linux drivers: principles and methods

IO memory application/return

Linux provides a set of functions for applying for and releasing IO memory ranges. These two APIs are not necessary when accessing IO memory, but they are recommended. They can check whether the applied resources are available and increase the efficiency of IO access. Security, if available, the application will be successful and marked as used. Other drivers will fail to apply before this process returns the resource.

**request_mem_region()**The macro function applies for n memory addresses from the memory. These addresses start from first, len is long, name represents the name of the device, and returns non-NULL on success and NULL on failure.

/**
 * 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() As the name suggests, the macro function returns the IO memory resources requested by request_mem_region()** to the kernel so that other processes can also access the IO memory.

/**
 * 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 memory mapping/unmapping

After applying for IO resources, the next step is to map the physical address to the virtual address. The API provided by the kernel is as follows

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

IO Memory Access API

ARM's SFR is 32bit. After we go through ioremap, we can actually read the obtained virtual address directly through forced type conversion. However, this method is not safe enough. If you are not careful, you will read the wrong address. For this reason, The kernel also provides a standard API to read and write IO memory. Not only is the code more secure, but the readability is also improved.

读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驱动开发中不可或缺的一部分,它可以实现对外设的控制和配置,也可以提升驱动程序的效率和兼容性。希望本文能够对你有所帮助和启发。

The above is the detailed content of I/O memory access technology in Linux drivers: principles and methods. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:lxlinux.net. If there is any infringement, please contact admin@php.cn delete