<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Linux設(shè)備驅(qū)動(dòng)之I/O端口與I/O內(nèi)存

          Linux設(shè)備驅(qū)動(dòng)之I/O端口與I/O內(nèi)存

          作者: 時(shí)間:2016-10-10 來源:網(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

          ……

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

          系統(tǒng)資源 占用

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

          BIOS 1M

          本地APIC 4K

          芯片組保留 2M

          IO APIC 4K

          PCI設(shè)備 256M

          PCI Express設(shè)備 256M

          PCI設(shè)備(可選) 256M

          顯示幀緩存 16M

          TSEG 1M

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

          二、linux I/O端口與I/O內(nèi)存

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

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

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

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

          1.IO寄存器和常規(guī)內(nèi)存

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

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

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

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

          2.操作IO端口(申請(qǐng),訪問,釋放):

          I/O 端口是驅(qū)動(dòng)用來和很多設(shè)備通訊的方法。

          (1)申請(qǐng)I/O 端口:

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

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

          (2)訪問IO端口:

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

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

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

          (3)釋放IO端口:

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



          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();