首頁  >  文章  >  系統教程  >  Linux驅動中的I/O記憶體存取技術:原理與方法

Linux驅動中的I/O記憶體存取技術:原理與方法

王林
王林轉載
2024-02-11 12:10:031239瀏覽

I/O內存是Linux系統中一種特殊的內存,它用來映射週邊裝置的暫存器,使得驅動程式可以透過讀寫記憶體來控制外設。 I/O記憶體的存取是Linux驅動開發中最常見的操作之一,它涉及實體位址和虛擬位址,連接埠映射和記憶體映射,位元組存取和字存取等概念。在本文中,我們將介紹Linux驅動程式中的I/O記憶體存取技術,並舉例說明它們的使用方法和注意事項。

Linux驅動中的I/O記憶體存取技術:原理與方法

#ARM是對記憶體空間和IO空間統一編址的,所以,透過讀寫SFR來控制硬體也就變成了透過讀寫對應的SFR位址來控制硬體。這部分位址也被稱為I/O記憶體。 x86中對I/O位址和記憶體位址是分開編址的,這樣的IO位址稱為I/O埠。本文只討論IO記憶體的存取

IO記憶體存取流程

#我們知道,為了管理最重要的系統資源並讓物理位址對進程透明,Linux使用了記憶體映射機制,就是一個進程如果想存取一個物理記憶體位址(eg.SFR位址),那麼首先就是將其映射成虛擬地址。

Linux驅動中的I/O記憶體存取技術:原理與方法

#」

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

以上是Linux驅動中的I/O記憶體存取技術:原理與方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:lxlinux.net。如有侵權,請聯絡admin@php.cn刪除