Linux 核心訪問外設IO資源的方式

2021-06-27 05:48:08 字數 2691 閱讀 6885

首先介紹一下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 ...