歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核驅動之I/O內存

Linux內核驅動之I/O內存

日期:2017/3/1 10:15:01   编辑:Linux內核

  幾乎每一種外設都是通過讀寫設備上的寄存器來進行的,通常包括控制寄存器、狀態寄存器和數據寄存器三大類,外設的寄存器通常被連續地編址。根據CPU體系結構的不同,CPU對IO端口的編址方式有兩種:

  (1)I/O映射方式(I/O-mapped)

  典型地,如X86處理器為外設專門實現了一個單獨的地址空間,稱為"I/O地址空間"或者"I/O端口空間",CPU通過專門的I/O指令(如X86的IN和OUT指令)來訪問這一空間中的地址單元。

  (2)內存映射方式(Memory-mapped)

  RISC指令系統的CPU(如ARM、PowerPC等)通常只實現一個物理地址空間,外設I/O端口成為內存的一部分。此時,CPU可以象訪問一個內存單元那樣訪問外設I/O端口,而不需要設立專門的外設I/O指令。

但是,這兩者在硬件實現上的差異對於軟件來說是完全透明的,驅動程序開發人員可以將內存映射方式的I/O端口和外設內存統一看作是"I/O內存"資源。

設備I/O內存訪問流程

1. I/O 內存分配

I/O 內存區必須在使用前分配. 分配內存區的接口是( 在 <linux/ioport.h> 定義):

struct resource *request_mem_region(unsigned long start, unsigned long len, char *name);

這個函數分配一個 len 字節的內存區, 從 start 開始. 如果一切順利, 一個 非NULL 指針返回; 否則返回值是 NULL. 所有的 I/O 內存分配來 /proc/iomem 中列出.

內存區在不再需要時應當釋放:

void release_mem_region(unsigned long start, unsigned long len);

2、物理地址映射到虛擬內存地址

#include <asm/io.h> void *ioremap(unsigned long phys_addr, unsigned long size); void iounmap(void * addr);

從 ioremap 返回的地址不應當直接解引用; 相反, 應當使用內核提供的存取函數.

3、 I/O 內存讀寫

使用 I/O 內存的正確方式是通過一系列為此而提供的函數(通過 <asm/io.h> 定義的).

從 I/O 內存讀, 使用下列之一:

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

這裡, addr 應當是從 ioremap 獲得的地址(也許與一個整型偏移); 返回值是從給定 I/O 內存讀取的.

有類似的一系列函數來寫 I/O 內存:

void iowrite8(u8 value, void *addr); void iowrite16(u16 value, void *addr); void iowrite32(u32 value, void *addr);
Copyright © Linux教程網 All Rights Reserved