首先介紹一下i/o埠和i/o記憶體。
1. i/o埠:當乙個暫存器或記憶體位於i/o空間時,稱其為i/o埠。
2. i/o記憶體:當乙個暫存器或記憶體位於記憶體空間時,稱其為i/o記憶體。
再來看一下i/o暫存器和常規記憶體的區別:i/o暫存器具有邊際效應(side
effect),而記憶體操作則沒有,記憶體寫操作的唯一結果就是在指定位置存貯乙個
數值;記憶體讀操作則僅僅是返回指定位置最後一次寫入的數值。何為邊際效應
呢?就是讀取某個位址時可能導致該位址內容發生變化。比如很多裝置的中斷
狀態暫存器只要一讀取,便自動清零。
現在來看一看如何在linux驅動程式中使用i/o埠和i/o記憶體。
使用i/o埠的步驟:
1. 申請
2. 訪問
3. 釋放
申請i/o埠:
在尚未對這些埠進行申請之前我們是不應該對這些埠進行操作的。核心為
我們提供了乙個註冊用的介面:
1. #include
2. struct resource *request_region(unsigned long first, unsigned long n, const char *name);
這個函式告訴核心,我們要使用起始於first的n個埠,引數name應該是設
備的名稱。如果分配成功,則返回非null。如果request_region返回null,
那麼我們就不能使用這些期望的埠。
訪問i/o埠:
訪問i/o埠時,多數硬體都會把8位,16位和32位的埠區分開。因此,c
語言程式中必須呼叫不同的函式來訪問大小不同的埠。
1. unsigned inb(unsigned port);
2. void outb(unsigned char byte, unsigned port);
位元組(8位寬度)讀寫埠。
1. unsigned inw(unsigned port);
2. void outw(unsigned short word, unsigned port);
讀寫16位埠。
1. unsigned inl(unsigned port);
2. void outl(unsigned longword, unsigned port);
讀寫32位埠。
釋放i/o埠:
如果不在使用某組i/o埠(可能在解除安裝模組時),則應該使用下面的函式將
這些埠返回給系統:
1. void release_region(unsigned long start, unsigned long n);
使用i/o記憶體的步驟:
1. 申請
2. 對映
3. 訪問
4. 釋放
根據計算機平台和所使用匯流排的不同,i/o記憶體可能是,也可能不是通過頁表
訪問的。如果訪問是經由頁表進行的,核心必須首先安排實體地址使其對裝置
驅動程式可見(這通常意味著在進行任何i/o之前必須先呼叫ioremap)。如果
訪問無需頁表,那麼i/o記憶體區域就非常類似於i/o埠,可以使用適當形式
的函式讀寫它們。
i/o記憶體申請:
1. struct resource *request_mem_region(unsigned long start, unsigned long len, char *name);
該函式從start開始分配len位元組長的記憶體區域。如果成功,返回非null指標;
否則返回null值。
i/o記憶體對映:
1. #include
2. void *ioremap(unsigned long phys_addr, unsigned long size);
把實體地址轉化成虛擬位址,返回值是虛擬位址。
1. void *iounmap(void *addr);
解除對映。
i/o記憶體訪問:
從記憶體中讀取:
1. unsigned int ioread8(void *addr);
2. unsigned int ioread16(void *addr);
3. unsigned int ioread32(void *addr);
其中addr應該是從ioremap獲得的位址。
還有一組寫入i/o記憶體類似函式:
1. void iowrite8(u8 value, void *addr);
2. void iowrite16(u16 value, void *addr);
3. void iowrite32(u32 value, void *addr);
i/o記憶體釋放:
1. void release_mem_region(unsigned long start, unsigned long len);
像i/o記憶體一樣使用i/o埠:
1. void *ioport_map(unsigned long port, unsigned int count);
該函式重新對映count個i/o埠,使其看起來像i/o記憶體。此後,驅動程式可
在該函式返回的位址上使用ioread8及其同類的函式。
當不再需要這種對映時,需要呼叫下面的函式來撤銷:
1. void ioport_unmap(void *addr);
核心訪問外設I O資源方式
參考 很多預設的外設i o資源是不在linux核心空間中,如sram 硬體暫存器,如果要訪問這些資源,就必須將它位址對映到核心空間。linux核心空間訪問外設i o資源有兩種方式 動態對映 ioremap 和靜態對映 map desc 一 動態對映 動態對映方式接觸應該比較多,即通過核心提供的ior...
Linux核心訪問外設I O資源的方式
linux核心訪問外設i o資源的方式 我們知道缺省外設i o資源是不在linux核心空間中的 如sram或硬體介面暫存器等 若需要訪問該外設i o資源,必須先將其位址對映到核心空間中來,然後才能在核心空間中訪問它。linux核心訪問外設i o記憶體資源的方式有兩種 動態對映 ioremap 和靜態...
外設I O資源的訪問方式
華清遠見嵌入式學院 講師。我們知道缺省外設i o資源是不在linux核心空間中的 如sram或硬體介面暫存器等 若需要訪問該外設i o資源,必須先將其位址對映到核心空間中來,然後才能在核心空間中訪問它。linux核心訪問外設i o記憶體資源的方式有兩種 動態對映 ioremap 和靜態對映 map ...