<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > Linux設備驅動(dòng)之I/O端口與I/O內存

Linux設備驅動(dòng)之I/O端口與I/O內存

作者: 時(shí)間:2016-10-10 來(lái)源:網(wǎng)絡(luò ) 收藏

0000-001f : dma1

0020-003f : pic1

0040-005f : timer

0060-006f : keyboard

0070-007f : rtc

0080-008f : dma page reg

00a0-00bf : pic2

00c0-00df : dma2

00f0-00ff : fpu

0170-0177 : ide1

……

不過(guò)Intel x86平臺普通使用了名為映射(MMIO)的技術(shù),該技術(shù)是PCI規范的一部分,IO設備被映射到空間,映射后,CPU訪(fǎng)問(wèn)IO就如同訪(fǎng)問(wèn)一樣??碔ntel TA 719文檔給出的x86/x64系統典型內存地址分配表:

系統資源 占用

------------------------------------------------------------------------

BIOS 1M

本地APIC 4K

芯片組保留 2M

IO APIC 4K

PCI設備 256M

PCI Express設備 256M

PCI設備(可選) 256M

顯示幀緩存 16M

TSEG 1M

對于某一既定的系統,它要么是獨立編址、要么是統一編址,具體采用哪一種則取決于CPU的體系結構。 如,PowerPC、m68k等采用統一編址,而X86等則采用獨立編址,存在IO空間的概念。目前,大多數嵌入式微控制器如ARM、PowerPC等并不提供I/O空間,僅有內存空間,可直接用地址、指針訪(fǎng)問(wèn)。但對于內核而言,它可能用于不同的CPU,所以它必須都要考慮這兩種方式,于是它采用一種新的方法,將基于I/O映射方式的或內存映射方式的I/O通稱(chēng)為“I/O區域”(I/O region),不論你采用哪種方式,都要先申請IO區域:request_resource(),結束時(shí)釋放它:release_resource()。

二、linux I/O端口與I/O內存

IO端口:當一個(gè)寄存器或者內存位于IO空間時(shí);

IO內存:當一個(gè)內存或者寄存器位于內存空間時(shí);

在一些CPU制造商在其芯片上實(shí)現了一個(gè)單地址空間(統一編址)的同時(shí),其它的CPU制造商認為外設不同于內存,應該有一個(gè)獨立的地址空間給外設(單獨編址),其生產(chǎn)處理器(特別是x86家族)的I/O端口有自己的讀寫(xiě)信號線(xiàn)和特殊的CPU指令來(lái)存取端口。因為外設要與外設總線(xiàn)相匹配,并且大部分流行的I/O總線(xiàn)都是以個(gè)人計算機(主要是x86家族)作為模型,所以即便那些沒(méi)有單獨地址空間給I/O端口的處理器,也必須在訪(fǎng)問(wèn)外設時(shí)模擬成讀寫(xiě)端口。這通常通過(guò)外部芯片組(PC中的南北橋)或者在CPU核中附加額外電路來(lái)實(shí)現(基于嵌入式應用的處理器)。

由于同樣的理由,在所有計算機平臺上都實(shí)現了I/O端口,甚至在那些單地址空間的CPU平臺上(模擬I/O端口)。但并不是所有的設備都會(huì )將其寄存器映射到I/O端口。雖然ISA設備普遍使用I/O端口,但大部分PCI設備將寄存器映射到某個(gè)內存地址區。這種I/O內存方法通常是首選的,因為它無(wú)需使用特殊的處理器指令,CPU存取內存也更有效率,并且編譯器在存取內存時(shí)在寄存器分配和尋址模式的選擇上有更多自由。

1.IO寄存器和常規內存

I/O寄存器和RAM的主要不同是I/O操作有邊際效應(side effect),而內存操作沒(méi)有:訪(fǎng)問(wèn)內存只是在內存某一位置存儲數值。因為內存存取速度嚴重影響CPU的性能,編譯器可能會(huì )對源碼進(jìn)行優(yōu)化,主要是:使用高速緩存和重排讀/寫(xiě)指令的順序。對于傳統內存(至少在單處理器系統)這些優(yōu)化是透明有益的,但是對于I/O 寄存器,這可能是致命錯誤,因為它們干擾了那些邊際效應(驅動(dòng)程序存取I/O 寄存器就是為了獲取邊際效應)。因此,驅動(dòng)程序必須確保在存取寄存器時(shí),不能使用高速緩存并且不能重新編排讀寫(xiě)指令的順序。

side effect 是指:訪(fǎng)問(wèn)I/O寄存器時(shí),不僅僅會(huì )像訪(fǎng)問(wèn)普通內存一樣影響存儲單元的值,更重要的是它可能改變CPU的I/O端口電平、輸出時(shí)序或CPU對I/O端口電平的反應等等,從而實(shí)現CPU的控制功能。CPU在電路中的意義就是實(shí)現其side effect 。舉個(gè)例子,有些設備的中斷狀態(tài)寄存器只要一讀取,便自動(dòng)清零。

硬件緩沖的問(wèn)題是最易解決的:只要將底層硬件配置(或者自動(dòng)地或者通過(guò) 初始化代碼)為當存取I/O區時(shí),禁止任何硬件緩沖(不管是I/O 內存還是I/O 端口)。

編譯器優(yōu)化和硬件重編排讀寫(xiě)指令順序的解決方法是:在硬件或處理器必須以一個(gè)特定順序執行的操作之間安放一個(gè)內存屏障(memory barrier)。

2.操作IO端口(申請,訪(fǎng)問(wèn),釋放):

I/O 端口是驅動(dòng)用來(lái)和很多設備通訊的方法。

(1)申請I/O 端口:

在驅動(dòng)還沒(méi)獨占設備之前,不應對端口進(jìn)行操作。內核提供了一個(gè)注冊接口,以允許驅動(dòng)聲明其需要的端口:

/* request_region告訴內核:要使用first開(kāi)始的n個(gè)端口。參數name為設備名。如果分配成功返回值是非NULL;否則無(wú)法使用需要的端口(/proc/ioports包含了系統當前所有端口的分配信息,若request_region分配失敗時(shí),可以查看該文件,看誰(shuí)先用了你要的端口) */struct resource *request_region(unsigned long first, unsigned long n, const char *name);

(2)訪(fǎng)問(wèn)IO端口:

在驅動(dòng)成功請求到I/O 端口后,就可以讀寫(xiě)這些端口了。大部分硬件會(huì )將8位、16位和32位端口區分開(kāi),無(wú)法像訪(fǎng)問(wèn)內存那樣混淆使用。驅動(dòng)程序必須調用不同的函數來(lái)訪(fǎng)問(wèn)不同大小的端口。

Linux 內核頭文件(體系依賴(lài)的頭文件) 定義了下列內聯(lián)函數來(lái)存取I/O端口:

/* inb/outb:讀/寫(xiě)字節端口(8位寬)。有些體系將port參數定義為unsigned long;而有些平臺則將它定義為unsigned short。inb的返回類(lèi)型也是依賴(lài)體系的 */unsigned inb(unsigned port);void outb(unsigned char byte, unsigned port);/* inw/outw:讀/寫(xiě)字端口(16位寬) */unsigned inw(unsigned port);void outw(unsigned short word, unsigned port);/* inl/outl:讀/寫(xiě)32位端口。longword也是依賴(lài)體系的,有的體系為unsigned long;而有的為unsigned int */unsigned inl(unsigned port);void outl(unsigned longword, unsigned port);

(3)釋放IO端口:

/* 用完I/O端口后(可能在模塊卸載時(shí)),應當調用release_region將I/O端口返還給系統。參數start和n應與之前傳遞給request_region一致 */void release_region(unsigned long start, unsigned long n);



關(guān)鍵詞: Linux 設備驅動(dòng) 端口 內存

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>