在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > [ARM筆記]設(shè)備IO端口和IO內(nèi)存的訪問

            [ARM筆記]設(shè)備IO端口和IO內(nèi)存的訪問

            作者: 時間:2016-12-05 來源:網(wǎng)絡(luò) 收藏

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

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

              1.  IO端口和IO內(nèi)存訪問接口

              1.1 IO端口

              在設(shè)備驅(qū)動中,應(yīng)使用內(nèi)核提供的函數(shù)來訪問定位于IO空間的端口,這些函數(shù)包括如下幾種:

              (1)讀寫字節(jié)端口(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);

              上述各函數(shù)中IO端口號port的類型高度依賴于具體的硬件平臺,因此,只是寫出了unsigned。

              1.2 IO內(nèi)存

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

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

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

              void iounmap(void *addr);

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

              (1)讀IO內(nèi)存

              unsigned int ioread8(void *addr);

              unsigned int ioread16(void *addr);

              unsigned int ioread32(void *addr);

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

              unsigned readb(address);

              unsigned readw(address);

              unsigned readl(address);

              (2)寫IO內(nèi)存

              void iowrite8(u8 value , void *addr);

              void iowrite16(u16 value , void *addr);

              void iowrite32(u32 value , void *addr);

              與上述函數(shù)對應(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)寫一串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);

              通過這個函數(shù),可以把port開始的count個連續(xù)的IO端口重映射為一段“內(nèi)存空間”。然后就可以在其返回的地址上像訪問IO內(nèi)存一樣訪問這些IO端口。當(dāng)不再需要這種映射時,需要調(diào)用下面的函數(shù)來撤銷。

              void ioport_unmap(void *addr);

              實(shí)際上,分析ioport_map()的源代碼可發(fā)現(xiàn),映射到內(nèi)存空間行為實(shí)際上是給開發(fā)人員制造的一個“假象”,并沒有映射到內(nèi)核虛擬地址,僅僅是為了讓工程師可使用統(tǒng)一的IO內(nèi)存訪問接口訪問IO端口。

              2. 申請與釋放設(shè)備IO端口和IO內(nèi)存

              2.1 IO端口申請

              Linux內(nèi)核提供了一組函數(shù)用于申請和釋放IO端口。

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

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

              當(dāng)用request_region()申請的IO端口使用完成后,應(yīng)當(dāng)使用release_region()函數(shù)將它們還給系統(tǒng),這個函數(shù)的原型如下:

              void release_region(resource_size_t start , resource_size_t n);

              2.2 IO內(nèi)存申請

              Linux內(nèi)核提供了一組函數(shù)用于申請和釋放IO內(nèi)存的范圍。

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

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

              當(dāng)用request_mem_region()申請的IO內(nèi)存使用完成后,應(yīng)當(dāng)使用release_region()函數(shù)將它們還給系統(tǒng),這個函數(shù)的原型如下:

              void release_region(resource_size_t start , resource_size_t n);

              上述request_region()和release_mem_region()都不是必須的,但建議使用。其任務(wù)是檢查申請的資源是否可用,如果可用則申請成功,并標(biāo)志為已經(jīng)使用,其他驅(qū)動想再次申請?jiān)撡Y源就會失敗。

              查看內(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)存訪問流程

              IO端口訪問的一種途徑是直接使用IO端口操作函數(shù):在設(shè)備打開或驅(qū)動模塊被加載時申請IO端口區(qū)域,之后使用inb()、outb()等進(jìn)行端口訪問,最后,在設(shè)備關(guān)閉或驅(qū)動被卸載時釋放IO端口范圍。

              ___________________________

              | |

              | request_region() | 在設(shè)備驅(qū)動模塊加載或open()函數(shù)中進(jìn)行

              |__________________________ |

              |

              ___________________________

              | |

              | inb()、outb()等 | 在設(shè)備驅(qū)動初始化、write()、read()、iotcl()等函數(shù)中進(jìn)行

              |__________________________ |

              |

              ___________________________

              | |

              | release_region()等 | 在設(shè)備驅(qū)動模塊卸載或release()函數(shù)中進(jìn)行

              |__________________________ |

              IO端口的訪問流程(不映射到內(nèi)存空間)

              IO端口訪問的另一種途徑是將IO端口映射為內(nèi)存進(jìn)行訪問:在設(shè)備打開或驅(qū)動模塊被加載時,申請IO端口區(qū)域并使用ioport_map()映射到內(nèi)存,之后使用IO內(nèi)存的函數(shù)進(jìn)行端口訪問,最后,在設(shè)備關(guān)閉或驅(qū)動被卸載時釋放IO端口并釋放映射。整個流程如下圖所示:

              ___________________________

              | |

              | request_region()等 | 

              |__________________________ | 

              |  在設(shè)備驅(qū)動模塊加載或open()函數(shù)中進(jìn)行

              ___________________________ /

              | | /

              | ioport_map()等 |

              |__________________________ |

              |

              ___________________________

              | |

              | ioread8、ioread16、 | 在設(shè)備驅(qū)動初始化、write()、read()、ioctl等函數(shù)中調(diào)用

              | ioread32、iowrite8等 |

              |__________________________ |

              |

              ___________________________

              | |

              | ioport_unmap() |

              |__________________________ | 

              | 

              ___________________________ /在設(shè)備驅(qū)動卸載或release()函數(shù)中調(diào)用

              | | /

              | release_region() | /

              |__________________________ |

              IO端口的訪問流程(映射到內(nèi)存空間)

              ___________________________________

              | |

              | request_mem_region()等 | 

              |__________________________________ | 

              |  在設(shè)備驅(qū)動模塊加載或open()函數(shù)中進(jìn)行

              __________________________________ /

              | | /

              | ioremap()等 |/

              |__________________________________|

              |

              ___________________________

              | |

              | ioread8、ioread16、 | 在設(shè)備驅(qū)動初始化、write()、read()、ioctl等函數(shù)中調(diào)用

              | ioread32、iowrite8等 |

              |__________________________ |

              |

              ______________________________

              | |

              | iounmap() | 

              |_____________________________ | 

              | 

              ______________________________ /在設(shè)備驅(qū)動卸載或release()函數(shù)中調(diào)用

              | | /

              | release_mem_region() | /

              |______________________________|



            關(guān)鍵詞: ARM Linux

            評論


            相關(guān)推薦

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

            關(guān)閉