學習Linux驅(qū)動開發(fā),先知道這些!
Linux驅(qū)動開發(fā)前奏
一、驅(qū)動開發(fā)概述
1.驅(qū)動分類,常規(guī)分類
字符設(shè)備:一種以字節(jié)為最小訪問單位的設(shè)備,通常支持open,close,read,write系統(tǒng)調(diào)用。
塊設(shè)備:大部分Unix系統(tǒng)中,以塊(通常是512字節(jié))為最小傳輸單位的設(shè)備,塊設(shè)備不能按字節(jié)處理數(shù)據(jù)。
網(wǎng)絡(luò)設(shè)備:可以是一個硬件設(shè)備,如網(wǎng)卡;也可以是一個純粹的軟件設(shè)備,比如回環(huán)接口(lo)。一個網(wǎng)絡(luò)接口負責發(fā)送和接受數(shù)據(jù)報文。
2.總線分類法
USB設(shè)備
PCI設(shè)備
平臺總線設(shè)備
二、驅(qū)動學習方法
1.驅(qū)動模型
分析范例程序、制作思維導圖、自己編寫代碼、驅(qū)動程序框架
2.硬件操作
復習裸機驅(qū)動
將裸機中的硬件操作移植到Linux驅(qū)動中
三、硬件訪問技術(shù)
1.1 硬件訪問實質(zhì)
驅(qū)動程序控制設(shè)備,主要是通過訪問設(shè)備內(nèi)的寄存器來達到控制目的,因此我們討論如何訪問硬件,就成了如何訪問這些寄存器了。
2. 地址映射
在Linux系統(tǒng)中,無論是內(nèi)核程序還是應(yīng)用程序,都只能使用虛擬地址,而芯片手冊中給出的硬件寄存器地址或者RAM地址則是物理地址,無法直接使用,因此,我們讀寫寄存器的第1步就是將將它的物理地址映射為虛擬地址。
2.1 動態(tài)映射
所謂動態(tài)映射,是指在驅(qū)動程序中采用ioremap函數(shù)將物理地址映射為虛擬地址。
原型:void * ioremap(physaddr, size)
參數(shù):
Physaddr:待映射的物理地址
Size: 映射的區(qū)域長度
返回值:映射后的虛擬地址
2.2 靜態(tài)映射
所謂靜態(tài)映射,是指Linux系統(tǒng)根據(jù)用戶事先指定的映射關(guān)系,在內(nèi)核啟動時,自動地將物理地址映射為虛擬地址。
1. 如何事先指定映射關(guān)系?????填充結(jié)構(gòu),告訴內(nèi)核map_desc數(shù)組中
2. 內(nèi)核啟動時,在什么地方完成自動映射? lotable_init();
2.3 映射關(guān)系
在靜態(tài)映射中,用戶是通過map_desc結(jié)構(gòu)來指明物理地址與虛擬地址的映射關(guān)系。
struct map_desc {
????unsigned long virtual; /* 映射后的虛擬地址 */
????unsigned long pfn; /* 物理地址所在的頁幀號 */
????unsigned long length; /* 映射長度 */
????unsigned int type; /* 映射的設(shè)備類型 */
};
pfn: 利用__phys_to_pfn(物理地址)可以計算出物理地址所在的物理頁幀號。
3.寄存器讀寫
在完成地址映射后,就可以讀寫寄存器了,Linux內(nèi)核提供了一系列函數(shù),來讀寫寄存器。
unsigned ioread8(void *addr)
unsigned ioread16(void *addr)
unsigned ioread32(void *addr)
unsigned readb(address)
unsigned readw(address)
unsigned readl(address)
void iowrite8(u8 value, void *addr)
void iowrite16(u16 value, void *addr)
void iowrite32(u32 value, void *addr)
void writeb(unsigned value, address)
void writew(unsigned value, address)
void writel(unsigned value, address)
? ? ? ? ?





