[ARM筆記]設備IO埠和IO內存的訪問

2020-12-25 電子產品世界

  設備通常會提供一組寄存器來用於控制設備、讀寫設備和獲取設備狀態,即控制寄存器、數據寄存器和狀態寄存器。這些寄存器可能位於IO空間,也可能位於內存空間。當位於IO空間時,通常被稱為IO埠,位於內存空間時,對應的內存空間成為IO內存。

本文引用地址:http://www.eepw.com.cn/article/201612/341120.htm

  1. Linux IO埠和IO內存訪問接口

  1.1 IO埠

  在Linux設備驅動中,應使用Linux內核提供的函數來訪問定位於IO空間的埠,這些函數包括如下幾種:

  (1)讀寫字節埠(8位寬)

  unsigned inb(unsigned port);

  void outb(unsigned char byte , unsigned port);

  (2)讀寫字埠(16位寬)

  unsigned inw(unsigned port);

  void outw(unsigned char byte , unsigned port);

  (3)讀寫長字埠(32位寬)

  unsigned inl(unsigned port);

  void outl(unsigned char byte , unsigned port);

  (4)讀寫一串字

  void insw(unsigned port , void *addr , unsigned long count);

  void outsw(unsigned port , void *addr , unsigned long count);

  (5)讀寫一串長字

  void insl(unsigned port , void *addr , unsigned long count);

  void outsl(unsigned port , void *addr , unsigned long count);

  上述各函數中IO埠號port的類型高度依賴於具體的硬體平臺,因此,只是寫出了unsigned。

  1.2 IO內存

  在內核中訪問IO內存之前,需首先使用ioremap()函數將設備所處的物理地址映射到虛擬地址。ioremap的原型如下:

  void *ioremap(unsigned long offset , unsigned long size);

  ioremap()與vmalloc()類似,也需要建立新的頁表,但是它並不進行vmalloc()中所執行的內存分配行為。ioremap()返回一個特殊的虛擬地址,該地址可用來存取特定的物理地址範圍。通過ioremap()獲得的虛擬地址應該被iounmap()函數釋放,其原型為:

  void iounmap(void *addr);

  在設備的物理地址被映射到虛擬地址之後,儘管可以直接通過指針訪問這些地址,但是可以使用Linux內核的如下一組函數來完成設備內存映射的虛擬地址的讀寫,這些函數如下所示。

  (1)讀IO內存

  unsigned int ioread8(void *addr);

  unsigned int ioread16(void *addr);

  unsigned int ioread32(void *addr);

  與上述函數對應的較早版本的函數為(這些函數在Linux2.6中仍然被支持):

  unsigned readb(address);

  unsigned readw(address);

  unsigned readl(address);

  (2)寫IO內存

  void iowrite8(u8 value , void *addr);

  void iowrite16(u16 value , void *addr);

  void iowrite32(u32 value , void *addr);

  與上述函數對應的較早版本的函數為(這些函數在Linux2.6中仍然被支持):

  unsigned writeb(address);

  unsigned writew(address);

  unsigned writel(address);

  (3)讀一串IO內存

  void ioread8_rep(void *addr , void *buf , unsigned long count);

  void ioread16_rep(void *addr , void *buf , unsigned long count);

  void ioread32_rep(void *addr , void *buf , unsigned long count);

  (4)寫一串IO內存

  void iowrite8_rep(void *addr , void *buf , unsigned long count);

  void iowrite16_rep(void *addr , void *buf , unsigned long count);

  void iowrite32_rep(void *addr , void *buf , unsigned long count);

  (5)複製IO內存

  void memcpy_fromio(void *dest , void *source , unsigned int count);

  void memcpy_toio(void *dest , void *source , unsigned int count);

  (6)設置IO內存

  void memset_io(void *addr , u8 value , unsigned int count);

  1.3 把IO埠映射到內存空間

  void *ioport_map(unsigned long port , unsigned int count);

  通過這個函數,可以把port開始的count個連續的IO埠重映射為一段「內存空間」。然後就可以在其返回的地址上像訪問IO內存一樣訪問這些IO埠。當不再需要這種映射時,需要調用下面的函數來撤銷。

  void ioport_unmap(void *addr);

  實際上,分析ioport_map()的原始碼可發現,映射到內存空間行為實際上是給開發人員製造的一個「假象」,並沒有映射到內核虛擬地址,僅僅是為了讓工程師可使用統一的IO內存訪問接口訪問IO埠。

  2. 申請與釋放設備IO埠和IO內存

  2.1 IO埠申請

  Linux內核提供了一組函數用於申請和釋放IO埠。

  struct resource *request_region(resource_size_t start, resource_size_t n, const char *name);

  這個函數向內核申請了n個埠,這些埠從first開始,name參數為設備的名稱。如果分配成功返回非NULL,失敗,則返回NULL。

  當用request_region()申請的IO埠使用完成後,應當使用release_region()函數將它們還給系統,這個函數的原型如下:

  void release_region(resource_size_t start , resource_size_t n);

  2.2 IO內存申請

  Linux內核提供了一組函數用於申請和釋放IO內存的範圍。

  struct resource *request_mem_region(resource_size_t start, resource_size_t n, const char *name, const char *name);

  這個函數向內核申請n個內存地址,這些地址從first開始,name參數為設備的名稱。如果分配成功返回值是非NULL,如果失敗,返回NULL。

  當用request_mem_region()申請的IO內存使用完成後,應當使用release_region()函數將它們還給系統,這個函數的原型如下:

  void release_region(resource_size_t start , resource_size_t n);

  上述request_region()和release_mem_region()都不是必須的,但建議使用。其任務是檢查申請的資源是否可用,如果可用則申請成功,並標誌為已經使用,其他驅動想再次申請該資源就會失敗。

  查看內核源碼可知,request_region()和request_mem_region()調用的函數是一樣的,只是傳入參數的不同。

  #define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name))

  #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name))

  3. 設備IO埠和IO內存訪問流程

  IO埠訪問的一種途徑是直接使用IO埠操作函數:在設備打開或驅動模塊被加載時申請IO埠區域,之後使用inb()、outb()等進行埠訪問,最後,在設備關閉或驅動被卸載時釋放IO埠範圍。

  ___________________________

  | |

  | request_region() | 在設備驅動模塊加載或open()函數中進行

  |__________________________ |

  |

  ___________________________

  | |

  | inb()、outb()等 | 在設備驅動初始化、write()、read()、iotcl()等函數中進行

  |__________________________ |

  |

  ___________________________

  | |

  | release_region()等 | 在設備驅動模塊卸載或release()函數中進行

  |__________________________ |

  IO埠的訪問流程(不映射到內存空間)

  IO埠訪問的另一種途徑是將IO埠映射為內存進行訪問:在設備打開或驅動模塊被加載時,申請IO埠區域並使用ioport_map()映射到內存,之後使用IO內存的函數進行埠訪問,最後,在設備關閉或驅動被卸載時釋放IO埠並釋放映射。整個流程如下圖所示:

  ___________________________

  | |

  | request_region()等 | \

  |__________________________ | \

  | \ 在設備驅動模塊加載或open()函數中進行

  ___________________________ /

  | | /

  | ioport_map()等 |

  |__________________________ |

  |

  ___________________________

  | |

  | ioread8、ioread16、 | 在設備驅動初始化、write()、read()、ioctl等函數中調用

  | ioread32、iowrite8等 |

  |__________________________ |

  |

  ___________________________

  | |

  | ioport_unmap() |\

  |__________________________ | \

  | \

  ___________________________ /在設備驅動卸載或release()函數中調用

  | | /

  | release_region() | /

  |__________________________ |

  IO埠的訪問流程(映射到內存空間)

  ___________________________________

  | |

  | request_mem_region()等 | \

  |__________________________________ | \

  | \ 在設備驅動模塊加載或open()函數中進行

  __________________________________ /

  | | /

  | ioremap()等 |/

  |__________________________________|

  |

  ___________________________

  | |

  | ioread8、ioread16、 | 在設備驅動初始化、write()、read()、ioctl等函數中調用

  | ioread32、iowrite8等 |

  |__________________________ |

  |

  ______________________________

  | |

  | iounmap() | \

  |_____________________________ | \

  | \

  ______________________________ /在設備驅動卸載或release()函數中調用

  | | /

  | release_mem_region() | /

  |______________________________|

相關焦點

  • 工業計算機不同的io埠解析
    工業電腦可以接受所有這些輸入,這歸功於您可以配置它們的各種輸入和輸出(I/O)埠。工業計算機不同的io埠1、串行埠串行埠是目前工業計算機中最常用的埠。它們使您的工業計算機和今天仍在生產工廠中使用的傳統設備之間實現通信。
  • 《Hole.io》卡住了黑屏怎麼辦 Hole.io卡屏黑屏解決方法詳解
    很多玩家可能還不太清楚,下面小編為大家帶來了Hole.io卡屏黑屏原因及解決方法一覽,感... Hole.io是一款非常好玩的遊戲,小夥伴們需要通過操控黑洞去吃球球獲得分數,那麼Hole.io卡屏黑屏怎麼辦?
  • 臨床級智能化醫療設備公司Healthy.io完成6000萬美元C輪融資
    【獵雲網北京】9月16日報導獵雲網今日獲悉,以色列特拉維夫臨床級智能化醫療設備公司Healthy.io宣布完成規模為6000萬美元的C輪融資,本輪投資人包括愉悅資本、Corner Ventures及此前輪次進入的Ansonia
  • Hole.io卡住了怎麼辦_Hole.io卡屏白屏BUG怎麼解決
    導 讀 Hole.io卡住了怎麼辦?Hole.io卡屏白屏BUG怎麼解決?
  • 在程序中如何正確地創建和銷毀軟體應用系統中文件IO流對象實例
    軟體項目實訓及課程設計指導——如何正確地創建和銷毀軟體應用系統中文件IO流對象實例1、Java文件輸入輸出(讀寫)相關的技術基礎知識(1)流(Stream)它是通過緩衝機制將數據從生產者(如鍵盤、磁碟文件、內存或其他設備
  • ifanr 訪談:Pip.io,野心勃勃的社交網絡平臺
    Pip.io 的兩位創始人:Leo Shimizu 和 David Chenifanr.com:Pip.io 的想法是怎麼來的?你們的目標是什麼?ifanr:Pip.io 的開發是什麼時候開始的?Leo:Pip.io 的開發工作在 2008 年初啟動,但直到 08 年 10 月我們才建立公司、開設辦公室。只有兩年而已啦!我覺得很酷的一點是我們比 Google Buzz 和 Wave 都早。
  • 在程序中如何正確地創建和銷毀軟體應用系統中文件IO流對象實例
    軟體項目實訓及課程設計指導——如何正確地創建和銷毀軟體應用系統中文件IO流對象實例1、Java文件輸入輸出(讀寫)相關的技術基礎知識(1)流(Stream)它是通過緩衝機制將數據從生產者(如鍵盤、磁碟文件、內存或其他設備
  • StoneFly虛擬IP SAN應用Fusion-io快閃記憶體
    DOSTOR存儲在線4月2日國際報導:StoneFly準備將Fusion-io伺服器快閃記憶體捆綁到它的虛擬IP SAN(存儲區域網)設備上,以便大幅提高性能。該公司提供以虛擬機形式運行的IP SAN或軟體,可以將分配好的主機伺服器的磁碟驅動器存儲轉變為iSCSI(網際網路小型計算機系統接口)存儲區域網資源,就像惠普的LeftHand虛擬存儲設備(VSA)所做的那樣。StoneFly有兩款SAN產品。SCVM(存儲集中器虛擬機)和ESS(企業存儲服務)。
  • Gate.io是哪個國家 比特兒gate.io交易平臺優缺點
    中億財經網5月30日訊,Gate.io交易中心哪個國家的?Gate.io著眼於做一家可信賴的安全性,平穩有信譽度的數字貨幣平臺交易。 中億財經網5月30日訊,Gate.io交易中心哪個國家的?Gate.io著眼於做一家可信賴的安全性,平穩有信譽度的數字貨幣平臺交易。
  • Gate.io 跨所禮遇一整月:他所VIP免費領Wallet.io S1、iPhone 12...
    *Wallet.io S1是全球首個支持在去中心化DeFi平臺上使用的指紋硬體錢包,收到硬體錢包進行初始化後,用戶可以直接接入電腦,參與河馬DeFi(https://www.hipo.com)去中心化平臺交易和流動性挖礦。
  • 安全至上——Gate.io芝麻開門的信仰
    Gate.io芝麻開門就是此類佼佼者的代表之一。Gate.io芝麻開門一直以來為用戶提供安全、快速、專業的數字貨幣交易服務。目前在全球多個國家和地區進行了合法註冊,一系列的安全屏障更是合力保障其經營著全球的商務、技術、Wallet.io、 GateChain、區塊鏈研究所等業務。
  • Filecoin主網上線在即 Gate.io或成交易首選平臺
    時隔3年,分布式存儲明星終將登上舞臺一展身手,而作為當前全球最大的FIL流通和交易市場,Gate.io芝麻開門交易所的一舉一動,也備受外界關注。Gate.io與 FIL的「前世今生」在過去的一個月中,整個Filecoin生態完全專注於太空競賽,這是Filecoin項目對網絡進行調整和升級來為主網啟動做準備的關鍵階段——整個生態通過大規模的實時壓力測試來積累有價值的知識和運營經驗。
  • 專訪諸葛io:數據分析,讓用戶「路人轉粉」的奇妙魔術
    而「一個行為和另一個行為之間的匹配關係」,就是規律。你手中掌握的規律越多,勝算越大。諸葛io 要做的,正是告訴企業他們的客戶,有怎樣的行為規律。他們判斷規律的方式,叫做「數據分析」。曾經擔任李開復的技術助理的他,發明了利用微博數據來評價人的系統:把一個人的微博資料,關注人的級別,他的訪問設備,被關注人的身份綜合起來,就可以得到這個人的精確社會定位。把這種數據分析的思想發揮到極致,就是利用「數據分析」來判斷用戶行為之間的關係。例如:用戶在 App 上點擊了怎樣的優惠活動,就會成為這個 App 的鐵粉。
  • t-io 3.5.8 發布,t-io 已經由杭州鈦特雲科技有限公司全職維護
    修改點 依賴版本升級 刪除了一些沒用的代碼POM坐標<dependency> <groupId>org.t-io</groupId> <artifactId>tio-core</artifactId> <version>3.5.8.v20191228-RELEASE</version></dependency>例行說明1. t-io已經由杭州鈦特雲科技有限公司全職維護
  • 微軟X-IO產品挑戰VMware和NFS組合
    Windows文件存儲產品經理Jose Barreto在博文中表示,使用Mellanox布線和交換機(今年5月在拉斯維加斯的Interop展示過)可以提供5.8GB/秒的文件提供速率。這個設置使用Windows Server 2012試用版和SMB 3.0。
  • 騰訊領投英國AI公司PROWLER.io
    PROWLER.io公司專注於數據高效性的方法及其『人機合作』技術,使之與眾不同,我們期待PROWLER.io將其AI決策平臺應用於更廣泛的客戶。」 PROWLER.io執行長Vishal Chatrath說:「發展AI平臺是我們的初心,我們很期待能藉助核心技術的靈活和創新,將產品擴展到新的垂直領域,希望未來能通過AI工具支持像騰訊、Pearson、Future Shape和Mandatum Life這樣的全球化企業和商業領導者,助其更好地決策。」
  • 逐浪創新競技安全,Gate.io如何掃除中心化交易所疑雲?
    而真正打消疑慮的,則是分享會最後與「神秘嘉賓」——Gate.io芝麻開門創始人韓林的連線。在加拿大拿到光學博士之後,韓林便一直定居在海外,目前Gate.io的運營主體也註冊在海外。據了解,Gate.io目前已獲得美國和加拿大的運營牌照,新加坡等多個海外地區的牌照也在持續申請中。
  • 一圖讀懂什麼是Gate.io芝麻開門牛熊證
    Gate.io芝麻開門牛熊證是一種提供看漲和看跌選擇的槓槓衍生品。Gate.io芝麻開門牛熊證的特點:1.現貨式簡單操作:牛熊證交易類似於現貨的買入賣出,無需保證金和其它操作,看漲買牛看跌買熊即可;2.高槓桿屬性:牛熊證具有槓桿高屬性,極端行情最高可達100-200倍;3.手續費低廉:與現貨以及合約比較,牛熊證交易手續費更低
  • Trip.io:區塊鏈在旅行住宿預訂領域落地
    Tripio 應運而生。作為基於區塊鏈的去中心化旅行服務市場平臺,Tripio 通過去中心化的區塊鏈網絡,直接連結全球旅行服務提供者(企業或個人)與消費者,以旅行住宿預訂為切入口,構建基於信任、激勵、零佣金的未來旅行服務生態。
  • 一圖讀懂什麼是Gate.io芝麻開門牛熊證
    Gate.io芝麻開門牛熊證是一種提供看漲和看跌選擇的槓槓衍生品。Gate.io芝麻開門牛熊證的特點:1.現貨式簡單操作:牛熊證交易類似於現貨的買入賣出,無需保證金和其它操作,看漲買牛看跌買熊即可;2.高槓桿屬性:牛熊證具有槓桿高屬性,極端行情最高可達100-200倍;3.手續費低廉:與現貨以及合約比較,牛熊證交易手續費更低