當(dāng)前位置:首頁(yè) > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]設(shè)備通常會(huì)提供一組寄存器來(lái)用于控制設(shè)備、讀寫(xiě)設(shè)備和獲取設(shè)備狀態(tài),即控制寄存器、數(shù)據(jù)寄存器和狀態(tài)寄存器。這些寄存器可能位于IO空間,也可能位于內(nèi)存空間。當(dāng)位于IO空間時(shí),通常被稱(chēng)為IO端口,位于內(nèi)存空間時(shí),對(duì)

設(shè)備通常會(huì)提供一組寄存器來(lái)用于控制設(shè)備、讀寫(xiě)設(shè)備和獲取設(shè)備狀態(tài),即控制寄存器、數(shù)據(jù)寄存器和狀態(tài)寄存器。這些寄存器可能位于IO空間,也可能位于內(nèi)存空間。當(dāng)位于IO空間時(shí),通常被稱(chēng)為IO端口,位于內(nèi)存空間時(shí),對(duì)應(yīng)的內(nèi)存空間成為IO內(nèi)存。

1. Linux IO端口和IO內(nèi)存訪(fǎng)問(wèn)接口
1.1 IO端口
在Linux設(shè)備驅(qū)動(dòng)中,應(yīng)使用Linux內(nèi)核提供的函數(shù)來(lái)訪(fǎng)問(wèn)定位于IO空間的端口,這些函數(shù)包括如下幾種:
(1)讀寫(xiě)字節(jié)端口(8位寬)
unsigned inb(unsigned port);
void outb(unsigned char byte , unsigned port);

(2)讀寫(xiě)字端口(16位寬)
unsigned inw(unsigned port);
void outw(unsigned char byte , unsigned port);

(3)讀寫(xiě)長(zhǎng)字端口(32位寬)
unsigned inl(unsigned port);
void outl(unsigned char byte , unsigned port);

(4)讀寫(xiě)一串字
void insw(unsigned port , void *addr , unsigned long count);
void outsw(unsigned port , void *addr , unsigned long count);

(5)讀寫(xiě)一串長(zhǎng)字
void insl(unsigned port , void *addr , unsigned long count);
void outsl(unsigned port , void *addr , unsigned long count);
上述各函數(shù)中IO端口號(hào)port的類(lèi)型高度依賴(lài)于具體的硬件平臺(tái),因此,只是寫(xiě)出了unsigned。

1.2 IO內(nèi)存
在內(nèi)核中訪(fǎng)問(wèn)IO內(nèi)存之前,需首先使用ioremap()函數(shù)將設(shè)備所處的物理地址映射到虛擬地址。ioremap的原型如下:
void *ioremap(unsigned long offset , unsigned long size);
ioremap()與vmalloc()類(lèi)似,也需要建立新的頁(yè)表,但是它并不進(jìn)行vmalloc()中所執(zhí)行的內(nèi)存分配行為。ioremap()返回一個(gè)特殊的虛擬地址,該地址可用來(lái)存取特定的物理地址范圍。通過(guò)ioremap()獲得的虛擬地址應(yīng)該被iounmap()函數(shù)釋放,其原型為:
void iounmap(void *addr);
在設(shè)備的物理地址被映射到虛擬地址之后,盡管可以直接通過(guò)指針訪(fǎng)問(wèn)這些地址,但是可以使用Linux內(nèi)核的如下一組函數(shù)來(lái)完成設(shè)備內(nèi)存映射的虛擬地址的讀寫(xiě),這些函數(shù)如下所示。
(1)讀IO內(nèi)存
unsigned int ioread8(void *addr);
unsigned int ioread16(void *addr);
unsigned int ioread32(void *addr);
與上述函數(shù)對(duì)應(yīng)的較早版本的函數(shù)為(這些函數(shù)在Linux2.6中仍然被支持):
unsigned readb(address);
unsigned readw(address);
unsigned readl(address);

(2)寫(xiě)IO內(nèi)存
void iowrite8(u8 value , void *addr);
void iowrite16(u16 value , void *addr);
void iowrite32(u32 value , void *addr);
與上述函數(shù)對(duì)應(yīng)的較早版本的函數(shù)為(這些函數(shù)在Linux2.6中仍然被支持):
unsigned writeb(address);
unsigned writew(address);
unsigned writel(address);

(3)讀一串IO內(nèi)存
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)寫(xiě)一串IO內(nèi)存
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)復(fù)制IO內(nèi)存
void memcpy_fromio(void *dest , void *source , unsigned int count);
void memcpy_toio(void *dest , void *source , unsigned int count);

(6)設(shè)置IO內(nèi)存
void memset_io(void *addr , u8 value , unsigned int count);

1.3 把IO端口映射到內(nèi)存空間
void *ioport_map(unsigned long port , unsigned int count);
通過(guò)這個(gè)函數(shù),可以把port開(kāi)始的count個(gè)連續(xù)的IO端口重映射為一段“內(nèi)存空間”。然后就可以在其返回的地址上像訪(fǎng)問(wèn)IO內(nèi)存一樣訪(fǎng)問(wèn)這些IO端口。當(dāng)不再需要這種映射時(shí),需要調(diào)用下面的函數(shù)來(lái)撤銷(xiāo)。
void ioport_unmap(void *addr);
實(shí)際上,分析ioport_map()的源代碼可發(fā)現(xiàn),映射到內(nèi)存空間行為實(shí)際上是給開(kāi)發(fā)人員制造的一個(gè)“假象”,并沒(méi)有映射到內(nèi)核虛擬地址,僅僅是為了讓工程師可使用統(tǒng)一的IO內(nèi)存訪(fǎng)問(wèn)接口訪(fǎng)問(wèn)IO端口。

2. 申請(qǐng)與釋放設(shè)備IO端口和IO內(nèi)存
2.1 IO端口申請(qǐng)
Linux內(nèi)核提供了一組函數(shù)用于申請(qǐng)和釋放IO端口。
struct resource *request_region(resource_size_t start, resource_size_t n, const char *name);
這個(gè)函數(shù)向內(nèi)核申請(qǐng)了n個(gè)端口,這些端口從first開(kāi)始,name參數(shù)為設(shè)備的名稱(chēng)。如果分配成功返回非NULL,失敗,則返回NULL。
當(dāng)用request_region()申請(qǐng)的IO端口使用完成后,應(yīng)當(dāng)使用release_region()函數(shù)將它們還給系統(tǒng),這個(gè)函數(shù)的原型如下:
void release_region(resource_size_t start , resource_size_t n);

2.2 IO內(nèi)存申請(qǐng)
Linux內(nèi)核提供了一組函數(shù)用于申請(qǐng)和釋放IO內(nèi)存的范圍。
struct resource *request_mem_region(resource_size_t start, resource_size_t n, const char *name, const char *name);
這個(gè)函數(shù)向內(nèi)核申請(qǐng)n個(gè)內(nèi)存地址,這些地址從first開(kāi)始,name參數(shù)為設(shè)備的名稱(chēng)。如果分配成功返回值是非NULL,如果失敗,返回NULL。
當(dāng)用request_mem_region()申請(qǐng)的IO內(nèi)存使用完成后,應(yīng)當(dāng)使用release_region()函數(shù)將它們還給系統(tǒng),這個(gè)函數(shù)的原型如下:
void release_region(resource_size_t start , resource_size_t n);
上述request_region()和release_mem_region()都不是必須的,但建議使用。其任務(wù)是檢查申請(qǐng)的資源是否可用,如果可用則申請(qǐng)成功,并標(biāo)志為已經(jīng)使用,其他驅(qū)動(dòng)想再次申請(qǐng)?jiān)撡Y源就會(huì)失敗。
查看內(nèi)核源碼可知,request_region()和request_mem_region()調(diào)用的函數(shù)是一樣的,只是傳入?yún)?shù)的不同。
#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. 設(shè)備IO端口和IO內(nèi)存訪(fǎng)問(wèn)流程
IO端口訪(fǎng)問(wèn)的一種途徑是直接使用IO端口操作函數(shù):在設(shè)備打開(kāi)或驅(qū)動(dòng)模塊被加載時(shí)申請(qǐng)IO端口區(qū)域,之后使用inb()、outb()等進(jìn)行端口訪(fǎng)問(wèn),最后,在設(shè)備關(guān)閉或驅(qū)動(dòng)被卸載時(shí)釋放IO端口范圍。
___________________________
||
| request_region() | 在設(shè)備驅(qū)動(dòng)模塊加載或open()函數(shù)中進(jìn)行
|__________________________|
|
___________________________
| |
| inb()、outb()等 | 在設(shè)備驅(qū)動(dòng)初始化、write()、read()、iotcl()等函數(shù)中進(jìn)行
|__________________________ |
|
___________________________
| |
| release_region()等 | 在設(shè)備驅(qū)動(dòng)模塊卸載或release()函數(shù)中進(jìn)行
|__________________________ |
IO端口的訪(fǎng)問(wèn)流程(不映射到內(nèi)存空間)

IO端口訪(fǎng)問(wèn)的另一種途徑是將IO端口映射為內(nèi)存進(jìn)行訪(fǎng)問(wèn):在設(shè)備打開(kāi)或驅(qū)動(dòng)模塊被加載時(shí),申請(qǐng)IO端口區(qū)域并使用ioport_map()映射到內(nèi)存,之后使用IO內(nèi)存的函數(shù)進(jìn)行端口訪(fǎng)問(wèn),最后,在設(shè)備關(guān)閉或驅(qū)動(dòng)被卸載時(shí)釋放IO端口并釋放映射。整個(gè)流程如下圖所示:
___________________________
| |
| request_region()等 |
|__________________________ |
| 在設(shè)備驅(qū)動(dòng)模塊加載或open()函數(shù)中進(jìn)行
___________________________ /
| | /
| ioport_map()等 |
|__________________________ |
|
___________________________
| |
| ioread8、ioread16、 | 在設(shè)備驅(qū)動(dòng)初始化、write()、read()、ioctl等函數(shù)中調(diào)用
| ioread32、iowrite8等|
|__________________________ |
|
___________________________
| |
| ioport_unmap()|
|__________________________ |
|
___________________________ /在設(shè)備驅(qū)動(dòng)卸載或release()函數(shù)中調(diào)用
| | /
| release_region()| /
|__________________________ |
IO端口的訪(fǎng)問(wèn)流程(映射到內(nèi)存空間)

___________________________________
| |
| request_mem_region()等|
|__________________________________ |
| 在設(shè)備驅(qū)動(dòng)模塊加載或open()函數(shù)中進(jìn)行
__________________________________ /
| | /
| ioremap()等 |/
|__________________________________|
|
___________________________
| |
| ioread8、ioread16、 | 在設(shè)備驅(qū)動(dòng)初始化、write()、read()、ioctl等函數(shù)中調(diào)用
| ioread32、iowrite8等 |
|__________________________ |
|
______________________________
| |
| iounmap() |
|_____________________________ |
|
______________________________ /在設(shè)備驅(qū)動(dòng)卸載或release()函數(shù)中調(diào)用
| | /
| release_mem_region() | /
|______________________________|

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀(guān)點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車(chē)的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車(chē)技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車(chē)工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車(chē)。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車(chē) 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶(hù)希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱(chēng),數(shù)字世界的話(huà)語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱(chēng)"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉