linux設備驅動程序開發
A. 如何編寫linux操作系統的設備驅動程序
Linux是Unix操作系統的一種變種,在Linux下編寫驅動程序的原理和
思想完全類似於其他的Unix系統,但它dos或window環境下的驅動程序有很大的
區別.在Linux環境下設計驅動程序,思想簡潔,操作方便,功能也很強大,但是
支持函數少,只能依賴kernel中的函數,有些常用的操作要自己來編寫,而且調
試也不方便.本人這幾周來為實驗室自行研製的一塊多媒體卡編制了驅動程序,
獲得了一些經驗,願與Linux fans共享,有不當之處,請予指正.
以下的一些文字主要來源於khg,johnsonm的Write linux device driver,
Brennan's Guide to Inline Assembly,The Linux A-Z,還有清華BBS上的有關
device driver的一些資料. 這些資料有的已經過時,有的還有一些錯誤,我依
據自己的試驗結果進行了修正.
一. Linux device driver 的概念
系統調用是操作系統內核和應用程序之間的介面,設備驅動程序是操作系統
內核和機器硬體之間的介面.設備驅動程序為應用程序屏蔽了硬體的細節,這樣
在應用程序看來,硬體設備只是一個設備文件, 應用程序可以象操作普通文件
一樣對硬體設備進行操作.設備驅動程序是內核的一部分,它完成以下的功能:
1.對設備初始化和釋放.
2.把數據從內核傳送到硬體和從硬體讀取數據.
3.讀取應用程序傳送給設備文件的數據和回送應用程序請求的數據.
4.檢測和處理設備出現的錯誤.
在Linux操作系統下有兩類主要的設備文件類型,一種是字元設備,另一種是
塊設備.字元設備和塊設備的主要區別是:在對字元設備發出讀/寫請求時,實際
的硬體I/O一般就緊接著發生了,塊設備則不然,它利用一塊系統內存作緩沖區,
當用戶進程對設備請求讀/寫時,它首先察看緩沖區的內容,如果緩沖區的數據
能滿足用戶的要求,就返回請求的數據,如果不能,就調用請求函數來進行實際
的I/O操作.塊設備是主要針對磁碟等慢速設備設計的,以免耗費過多的CPU時間
來等待.
已經提到,用戶進程是通過設備文件來與實際的硬體打交道.每個設備文件都
都有其文件屬性(c/b),表示是字元設備還蔤強檣璞?另外每個文件都有兩個設
備號,第一個是主設備號,標識驅動程序,第二個是從設備號,標識使用同一個
設備驅動程序的不同的硬體設備,比如有兩個軟盤,就可以用從設備號來區分
他們.設備文件的的主設備號必須與設備驅動程序在登記時申請的主設備號
一致,否則用戶進程將無法訪問到驅動程序.
最後必須提到的是,在用戶進程調用驅動程序時,系統進入核心態,這時不再是
搶先式調度.也就是說,系統必須在你的驅動程序的子函數返回後才能進行其他
的工作.如果你的驅動程序陷入死循環,不幸的是你只有重新啟動機器了,然後就
B. 如何編寫Linux 驅動程序
以裝載和卸載模塊為例:
1、首先輸入代碼
#include <linux/init.h>
#include <linux/mole.h>
C. Linux內核開發與Linux驅動開發有什麼關系
驅動裝在系統上,有的會跟內核有交互,但是驅動一般是針對設備
D. linux驅動開發要有哪些基礎
需要一定的努力才可以學好:
Linux設備驅動是linux內核的一部分,是用來屏蔽硬體細節,為上層提供標准介面的一種技術手段。為了能夠編寫出質量比較高的驅動程序,要求工程師必須具備以下幾個方面的知識:
1、 熟悉處理器的性能
如:處理器的體系結構、匯編語言、工作模式、異常處理等。對於初學者來說,在還不熟悉驅動編寫方法的情況下,可以先不把重心放在這一項上,因為可能因為它的枯燥、抽象而影響到你對設備驅動的興趣。隨著你不斷地熟悉驅動的編寫,你會很自然的意識到此項的重要性。
2、掌握驅動目標的硬體工作原理及通訊協議
如:串口控制器、顯卡控制器、硬體編解碼、存儲卡控制器、I2C通訊、SPI通訊、USB通訊、SDIO通訊、I2S通訊、PCI通訊等。編寫設備驅動的前提就是需要了解設備的操作方法,所以這些內容的重要程度不言而喻。但不是說要把所有設備的操作方法都熟悉了以後才可以寫驅動,你只需要了解你要驅動的硬體就可以了。
一、掌握硬體的控制方法
如:中斷、輪詢、DMA 等,通常一個硬體控制器會有多種控制方法,你需要根據系統性能的需要合理的選擇操作方法。初學階段以實現功能為目的,掌握的順序應該是,輪詢->中斷->DMA。隨著學習的深入,需要綜合考慮系統的性能需求,採取合適的方法。
二、良好的GNU C語言編程基礎
如:C語言的指針、結構體、內存操作、鏈表、隊列、棧、C和匯編混合編程等。這些編程語法是編寫設備驅動的基礎,無論對於初學者還是有經驗者都非常重要。
三、 良好的linux操作系統概念
如:多進程、多線程、進程調度、進程搶占、進程上下文、虛擬內存、原子操作、阻塞、睡眠、同步等概念及它們之間的關系。這些概念及方法在設備驅動里的使用是linux設備驅動區別單片機編程的最大特點,只有理解了它們才會編寫出高質量的驅動。
四、掌握linux內核中設備驅動的編寫介面
如:字元設備的cdev、塊設備的gendisk、網路設備的net_device,以及基於這些基本介面的framebuffer設備的fb_info、mtd設備的mtd_info、tty設備的tty_driver、usb設備的usb_driver、mmc設備的mmc_host等。
E. 怎樣入門Linux驅動程序開發,如:網卡驅動。
網卡驅動不涉及網路編程,所謂驅動就是硬體和OS通信的橋梁。想學linux驅動,自己網上買塊開發板,買本linux設備驅動程序的書,然後從最簡單的key驅動開始,然後觸屏驅動,由淺入深。
F. linux設備驅動程序開發應該怎麼入手
不說說你當前基礎嗎?
1.熟練使用C語言和基本數據結構
2.熟悉Linux環境編程環境
3.良好的數字電路基礎
4.了解操作系統原理,了解linux驅動的基本原理和實現方法
可按上面順序學習,多動手實踐
G. 什麼是linux 平台驅動開發
在學習之前一直對驅動開發非常的陌生,感覺有點神秘。不知道驅動開發和普通的程序開發究竟有什麼不同;它的基本框架又是什麼樣的;他的開發環境有什麼特殊的地方;以及怎麼寫編寫一個簡單的字元設備驅動前編譯載入,下面我就對這些問題一個一個的介紹。
一、驅動的基本框架
1. 那麼究竟什麼是驅動程序,它有什麼用呢:
l 驅動是硬體設備與應用程序之間的一個中間軟體層
l 它使得某個特定硬體能夠響應一個定義良好的內部編程介面,同時完全隱蔽了設備的工作細節
l 用戶通過一組與具體設備無關的標准化的調用來完成相應的操作
l 驅動程序的任務就是把這些標准化的系統調用映射到具體設備對於實際硬體的特定操作上
l 驅動程序是內核的一部分,可以使用中斷、DMA等操作
l 驅動程序在用戶態和內核態之間傳遞數據
2. Linux驅動的基本框架
3. Linux下設備驅動程序的一般可以分為以下三類
1) 字元設備
a) 所有能夠象位元組流一樣訪問的設備都通過字元設備來實現
b) 它們被映射為文件系統中的節點,通常在/dev/目錄下面
c) 一般要包含open read write close等系統調用的實現
2) 塊設備
d) 通常是指諸如磁碟、內存、Flash等可以容納文件系統的存儲設備。
e) 塊設備也是通過文件系統來訪問,與字元設備的區別是:內核管理數據的方式不同
f) 它允許象字元設備一樣以位元組流的方式來訪問,也可一次傳遞任意多的位元組。
3) 網路介面設備
g) 通常它指的是硬體設備,但有時也可能是一個軟體設備(如回環介面loopback),它們由內核中網路子系統驅動,負責發送和接收數據包。
h) 它們的數據傳送往往不是面向流的,因此很難將它們映射到一個文件系統的節點上。
二、怎麼搭建一個驅動的開發環境
因為驅動是要編譯進內核,在啟動內核時就會驅動此硬體設備;或者編譯生成一個.o文件, 當應用程序需要時再動態載入進內核空間運行。因此編譯任何一個驅動程序都要鏈接到內核的源碼樹。所以搭建環境的第一步當然是建內核源碼樹
1. 怎麼建內核源碼樹
a) 首先看你的系統有沒有源碼樹,在你的/lib/ moles目錄下會有內核信息,比如我當前的系統里有兩個版本:
#ls /lib/ moles
2.6.15-rc7 2.6.21-1.3194.fc7
查看其源碼位置:
## ll /lib/moles/2.6.15-rc7/build
lrwxrwxrwx 1 root root 27 2008-04-28 19:19 /lib/moles/2.6.15-rc7/build -> /root/xkli/linux-2.6.15-rc7
發現build是一個鏈接文件,其所對應的目錄就是源碼樹的目錄。但現在這里目標目錄已經是無效的了。所以得自己重新下載
b)下載並編譯源碼樹
有很多網站上可以下載,但官方網址是:
http://www.kernel.org/pub/linux/kernel/v2.6/
下載完後當然就是解壓編譯了
# tar –xzvf linux-2.6.16.54.tar.gz
#cd linux-2.6.16.54
## make menuconfig (配置內核各選項,如果沒有配置就無法下一步編譯,這里可以不要改任何東西)
#make
…
如果編譯沒有出錯。那麼恭喜你。你的開發環境已經搭建好了
三、了解驅動的基本知識
1. 設備號
1) 什麼是設備號呢?我們進系統根據現有的設備來講解就清楚了:
#ls -l /dev/
crwxrwxrwx 1 root root 1, 3 2009-05-11 16:36 null
crw------- 1 root root 4, 0 2009-05-11 16:35 systty
crw-rw-rw- 1 root tty 5, 0 2009-05-11 16:36 tty
crw-rw---- 1 root tty 4, 0 2009-05-11 16:35 tty0
在日期前面的兩個數(如第一列就是1,3)就是表示的設備號,第一個是主設備號,第二個是從設備號
2) 設備號有什麼用呢?
l 傳統上, 主編號標識設備相連的驅動. 例如, /dev/null 和 /dev/zero 都由驅動 1 來管理, 而虛擬控制台和串口終端都由驅動 4 管理
l 次編號被內核用來決定引用哪個設備. 依據你的驅動是如何編寫的自己區別
3) 設備號結構類型以及申請方式
l 在內核中, dev_t 類型(在 中定義)用來持有設備編號, 對於 2.6.0 內核, dev_t 是 32 位的量, 12 位用作主編號, 20 位用作次編號.
l 能獲得一個 dev_t 的主或者次編號方式:
MAJOR(dev_t dev); //主要
MINOR(dev_t dev);//次要
l 但是如果你有主次編號, 需要將其轉換為一個 dev_t, 使用: MKDEV(int major, int minor);
4) 怎麼在程序中分配和釋放設備號
在建立一個字元驅動時需要做的第一件事是獲取一個或多個設備編號來使用. 可以達到此功能的函數有兩個:
l 一個是你自己事先知道設備號的
register_chrdev_region, 在 中聲明:
int register_chrdev_region(dev_t first, unsigned int count, char *name);
first 是你要分配的起始設備編號. first 的次編號部分常常是 0,count 是你請求的連續設備編號的總數. name 是應當連接到這個編號范圍的設備的名子; 它會出現在 /proc/devices 和 sysfs 中.
l 第二個是動態動態分配設備編號
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
使用這個函數, dev 是一個只輸出的參數, 它在函數成功完成時持有你的分配范圍的第一個數. fisetminor 應當是請求的第一個要用的次編號; 它常常是 0. count 和 name 參數如同給 request_chrdev_region 的一樣.
5) 設備編號的釋放使用
不管你是採用哪些方式分配的設備號。使用之後肯定是要釋放的,其方式如下:
void unregister_chrdev_region(dev_t first, unsigned int count);
6)
2. 驅動程序的二個最重要數據結構
1) file_operation
倒如字元設備scull的一般定義如下:
struct file_operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};
file_operation也稱為設備驅動程序介面
定義在 , 是一個函數指針的集合. 每個打開文件(內部用一個 file 結構來代表)與它自身的函數集合相關連( 通過包含一個稱為 f_op 的成員, 它指向一個 file_operations 結構). 這些操作大部分負責實現系統調用, 因此, 命名為 open, read, 等等
2) File
定義位於include/fs.h
struct file結構與驅動相關的成員
l mode_t f_mode 標識文件的讀寫許可權
l loff_t f_pos 當前讀寫位置
l unsigned int_f_flag 文件標志,主要進行阻塞/非阻塞型操作時檢查
l struct file_operation * f_op 文件操作的結構指針
l void * private_data 驅動程序一般將它指向已經分配的數據
l struct dentry* f_dentry 文件對應的目錄項結構
3. 字元設備注冊
1) 內核在內部使用類型 struct cdev 的結構來代表字元設備. 在內核調用你的設備操作前, 必須編寫分配並注冊一個或幾個這些結構. 有 2 種方法來分配和初始化一個這些結構.
l 如果你想在運行時獲得一個獨立的 cdev 結構,可以這樣使用:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_fops;
l 如果想將 cdev 結構嵌入一個你自己的設備特定的結構; 你應當初始化你已經分配的結構, 使用:
void cdev_init(struct cdev *cdev, struct file_operations *fops);
2) 一旦 cdev 結構建立, 最後的步驟是把它告訴內核, 調用:
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
說明:dev 是 cdev 結構, num 是這個設備響應的第一個設備號, count 是應當關聯到設備的設備號的數目. 常常 count 是 1, 但是有多個設備號對應於一個特定的設備的情形.
3) 為從系統去除一個字元設備, 調用:
void cdev_del(struct cdev *dev);
4. open 和 release
H. 如何系統的學習Linux驅動開發
在學習之前一直對驅動開發非常的陌生,感覺有點神秘。不知道驅動開發和普通的程序開發究竟有什麼不同;它的基本框架又是什麼樣的;他的開發環境有什麼特殊的地方;以及怎麼寫編寫一個簡單的字元設備驅動前編譯載入,下面我就對這些問題一個一個的介紹。
一、驅動的基本框架
1.那麼究竟什麼是驅動程序,它有什麼用呢:
l驅動是硬體設備與應用程序之間的一個中間軟體層
l它使得某個特定硬體能夠響應一個定義良好的內部編程介面,同時完全隱蔽了設備的工作細節
l用戶通過一組與具體設備無關的標准化的調用來完成相應的操作
l驅動程序的任務就是把這些標准化的系統調用映射到具體設備對於實際硬體的特定操作上
l驅動程序是內核的一部分,可以使用中斷、DMA等操作
l驅動程序在用戶態和內核態之間傳遞數據
2.Linux驅動的基本框架
3.Linux下設備驅動程序的一般可以分為以下三類
1)字元設備
a)所有能夠象位元組流一樣訪問的設備都通過字元設備來實現
b)它們被映射為文件系統中的節點,通常在/dev/目錄下面
c)一般要包含open read write close等系統調用的實現
2)塊設備
d)通常是指諸如磁碟、內存、Flash等可以容納文件系統的存儲設備。
e)塊設備也是通過文件系統來訪問,與字元設備的區別是:內核管理數據的方式不同
f)它允許象字元設備一樣以位元組流的方式來訪問,也可一次傳遞任意多的位元組。
3)網路介面設備
g)通常它指的是硬體設備,但有時也可能是一個軟體設備(如回環介面loopback),它們由內核中網路子系統驅動,負責發送和接收數據包。
h)它們的數據傳送往往不是面向流的,因此很難將它們映射到一個文件系統的節點上。
二、怎麼搭建一個驅動的開發環境
因為驅動是要編譯進內核,在啟動內核時就會驅動此硬體設備;或者編譯生成一個.o文件,當應用程序需要時再動態載入進內核空間運行。因此編譯任何一個驅動程序都要鏈接到內核的源碼樹。所以搭建環境的第一步當然是建內核源碼樹
1.怎麼建內核源碼樹
a)首先看你的系統有沒有源碼樹,在你的/lib/ moles目錄下會有內核信息,比如我當前的系統里有兩個版本:
#ls /lib/ moles
2.6.15-rc72.6.21-1.3194.fc7
查看其源碼位置:
## ll /lib/moles/2.6.15-rc7/build
lrwxrwxrwx 1 root root 27 2008-04-28 19:19 /lib/moles/2.6.15-rc7/build -> /root/xkli/linux-2.6.15-rc7
發現build是一個鏈接文件,其所對應的目錄就是源碼樹的目錄。但現在這里目標目錄已經是無效的了。所以得自己重新下載
b)下載並編譯源碼樹
有很多網站上可以下載,但官方網址是:
http://www.kernel.org/pub/linux/kernel/v2.6/
下載完後當然就是解壓編譯了
# tar –xzvf linux-2.6.16.54.tar.gz
#cd linux-2.6.16.54
## make menuconfig (配置內核各選項,如果沒有配置就無法下一步編譯,這里可以不要改任何東西)
#make
…
如果編譯沒有出錯。那麼恭喜你。你的開發環境已經搭建好了
三、了解驅動的基本知識
1.設備號
1)什麼是設備號呢?我們進系統根據現有的設備來講解就清楚了:
#ls -l /dev/
crwxrwxrwx 1 root root1,3 2009-05-11 16:36 null
crw------- 1 root root4,0 2009-05-11 16:35 systty
crw-rw-rw- 1 root tty5,0 2009-05-11 16:36 tty
crw-rw---- 1 root tty4,0 2009-05-11 16:35 tty0
在日期前面的兩個數(如第一列就是1,3)就是表示的設備號,第一個是主設備號,第二個是從設備號
2)設備號有什麼用呢?
l傳統上,主編號標識設備相連的驅動.例如, /dev/null和/dev/zero都由驅動1來管理,而虛擬控制台和串口終端都由驅動4管理
l次編號被內核用來決定引用哪個設備.依據你的驅動是如何編寫的自己區別
3)設備號結構類型以及申請方式
l在內核中, dev_t類型(在中定義)用來持有設備編號,對於2.6.0內核, dev_t是32位的量, 12位用作主編號, 20位用作次編號.
l能獲得一個dev_t的主或者次編號方式:
MAJOR(dev_t dev); //主要
MINOR(dev_t dev);//次要
l但是如果你有主次編號,需要將其轉換為一個dev_t,使用: MKDEV(int major, int minor);
4)怎麼在程序中分配和釋放設備號
在建立一個字元驅動時需要做的第一件事是獲取一個或多個設備編號來使用.可以達到此功能的函數有兩個:
l一個是你自己事先知道設備號的
register_chrdev_region,在中聲明:
int register_chrdev_region(dev_t first, unsigned int count, char *name);
first是你要分配的起始設備編號. first的次編號部分常常是0,count是你請求的連續設備編號的總數. name是應當連接到這個編號范圍的設備的名子;它會出現在/proc/devices和sysfs中.
l第二個是動態動態分配設備編號
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
使用這個函數, dev是一個只輸出的參數,它在函數成功完成時持有你的分配范圍的第一個數. fisetminor應當是請求的第一個要用的次編號;它常常是0. count和name參數如同給request_chrdev_region的一樣.
5)設備編號的釋放使用
不管你是採用哪些方式分配的設備號。使用之後肯定是要釋放的,其方式如下:
void unregister_chrdev_region(dev_t first, unsigned int count);
6)
2.驅動程序的二個最重要數據結構
1)file_operation
倒如字元設備scull的一般定義如下:
struct file_operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};
file_operation也稱為設備驅動程序介面
定義在,是一個函數指針的集合.每個打開文件(內部用一個file結構來代表)與它自身的函數集合相關連(通過包含一個稱為f_op的成員,它指向一個file_operations結構).這些操作大部分負責實現系統調用,因此,命名為open, read,等等
2)File
定義位於include/fs.h
struct file結構與驅動相關的成員
lmode_t f_mode標識文件的讀寫許可權
lloff_t f_pos當前讀寫位置
lunsigned int_f_flag文件標志,主要進行阻塞/非阻塞型操作時檢查
lstruct file_operation * f_op文件操作的結構指針
lvoid * private_data驅動程序一般將它指向已經分配的數據
lstruct dentry* f_dentry文件對應的目錄項結構
3.字元設備注冊
1)內核在內部使用類型struct cdev的結構來代表字元設備.在內核調用你的設備操作前,必須編寫分配並注冊一個或幾個這些結構.有2種方法來分配和初始化一個這些結構.
l如果你想在運行時獲得一個獨立的cdev結構,可以這樣使用:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_fops;
l如果想將cdev結構嵌入一個你自己的設備特定的結構;你應當初始化你已經分配的結構,使用:
void cdev_init(struct cdev *cdev, struct file_operations *fops);
2)一旦cdev結構建立,最後的步驟是把它告訴內核,調用:
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
說明:dev是cdev結構, num是這個設備響應的第一個設備號, count是應當關聯到設備的設備號的數目.常常count是1,但是有多個設備號對應於一個特定的設備的情形.
3)為從系統去除一個字元設備,調用:
void cdev_del(struct cdev *dev);
4.open和release
I. Linux驅動程序開發實例的目錄
前言
第1章 Linux設備驅動程序模型 1
1.1 設備驅動程序基礎 1
1.1.1 驅動程序的概念 1
1.1.2 驅動程序的載入方式 2
1.1.3 編寫可載入模塊 3
1.1.4 帶參數的可載入模塊 5
1.1.5 設備驅動程序的分類 6
1.2 字元設備驅動程序原理 7
1.2.1 file_operations結構 7
1.2.2 使用register_chrdev注冊字元
設備 9
1.2.3 使用cdev_add注冊字元設備 11
1.2.4 字元設備的讀寫 13
1.2.5 ioctl介面 14
1.2.6 seek介面 16
1.2.7 poll介面 18
1.2.8 非同步通知 22
1.3 proc文件系統 24
1.3.1 proc文件系統概述 24
1.3.2 seq_file機制 25
1.3.3 使用proc文件系統 27
1.4 塊設備驅動程序 32
1.4.1 Linux塊設備驅動程序原理 32
1.4.2 簡單的塊設備驅動程序實例 35
1.5 網路設備驅動程序 39
1.5.1 網路設備的特殊性 39
1.5.2 sk_buff結構 40
1.5.3 Linux網路設備驅動程序架構 42
1.5.4 虛擬網路設備驅動程序實例 46
1.6 Linux 2.6設備管理機制 50
1.6.1 kobject和kset 50
1.6.2 sysfs文件系統 51
1.6.3 設備模型層次 52
1.6.4 platform的概念 54
第2章 Linux內核同步機制 58
2.1 鎖機制 58
2.1.1 自旋鎖 58
2.1.2 讀寫鎖 60
2.1.3 RCU 61
2.2 互斥 64
2.2.1 原子操作 64
2.2.2 信號量 65
2.2.3 讀寫信號量 67
2.3 等待隊列 68
2.3.1 等待隊列原理 68
2.3.2 阻塞式I/O實例 68
2.3.3 完成事件 70
2.4 關閉中斷 71
第3章 內存管理與鏈表 72
3.1 物理地址和虛擬地址 72
3.2 內存分配與釋放 72
3.3 IO埠到虛擬地址的映射 73
3.3.1 靜態映射 73
3.3.2 動態映射 75
3.4 內核空間到用戶空間的映射 76
3.4.1 內核空間到用戶空間的地址
映射原理 76
3.4.2 mmap地址映射實例 78
3.5 內核鏈表 80
3.5.1 Linux內核中的鏈表 80
3.5.2 內核鏈表實例 81
第4章 延遲處理 83
4.1 內核線程 83
4.2 軟中斷機制 85
4.2.1 軟中斷原理 85
4.2.2 tasklet 87
4.3 工作隊列 89
4.3.1 工作隊列原理 89
4.3.2 工作隊列實例 91
4.4 內核時間 92
4.4.1 Linux中的時間概念 92
4.4.2 Linux中的延遲 93
4.4.3 內核定時器 93
第5章 簡單設備驅動程序 96
5.1 寄存器訪問 96
5.1.1 S3C6410地址映射 96
5.1.2 S3C6410看門狗驅動程序實例 98
5.1.3 S3C6410蜂鳴器驅動程序實例 102
5.2 電平控制 107
5.2.1 S3C6410 LED驅動程序實例 107
5.2.2 掃描型S3C6410按鍵驅動
程序實例 109
5.3 時序產生 112
5.3.1 時序圖原理 112
5.3.2 AT24C02晶元原理 112
5.3.3 AT24C02驅動程序開發實例 115
5.4 硬中斷處理 123
5.4.1 硬中斷處理原理 123
5.4.2 中斷型S3C6410按鍵驅動
程序實例 127
5.5 Linux I/O埠控制 132
5.5.1 Linux I/O埠讀寫 132
5.5.2 在應用層訪問Linux I/O
埠 133
5.5.3 /dev/port設備 134
第6章 深入Linux內核 135
6.1 嵌入式Linux系統構成 135
6.2 Linux內核導讀 136
6.2.1 Linux內核組成 136
6.2.2 Linux的代碼結構 137
6.2.3 內核Makefile 138
6.2.4 S3C6410硬體初始化 139
6.3 Linux文件系統 141
6.3.1 虛擬文件系統 141
6.3.2 根文件系統 143
6.3.3 文件系統載入 143
6.3.4 ext3文件系統 145
6.4 Flash文件系統 145
6.4.1 MTD設備 145
6.4.2 MTD字元設備 148
6.4.3 MTD塊設備 150
6.4.4 cramfs文件系統 153
6.4.5 JFFS2文件系統 153
6.4.6 YAFFS文件系統 155
6.4.7 文件系統總結 156
6.5 Linux內核移植 156
6.5.1 體系配置 156
6.5.2 添加yaffs2 157
6.5.3 Nand flash驅動程序移植 157
6.5.4 配置啟動參數 159
6.5.5 移植RTC驅動程序 160
6.6 根文件系統製作 162
6.6.1 Busybox 162
6.6.2 shell基礎 165
6.6.3 根文件系統構建實例 166
6.7 udev模型 167
6.7.1 udev模型原理 167
6.7.2 mdev的使用 167
第7章 I2C匯流排驅動程序 169
7.1 Linux的I2C驅動程序架構 169
7.1.1 I2C適配器 169
7.1.2 I2C演算法 170
7.1.3 I2C驅動程序結構 170
7.1.4 I2C從設備 171
7.1.5 i2c-dev設備層 171
7.2 Linux I2C驅動程序開發 174
7.2.1 S3C2410X的I2C控制器 174
7.2.2 S3C2410X的I2C驅動程序
分析 175
7.3 S3C2410的I2C訪問實例 182
7.4 I2C客戶端驅動程序 185
第8章 TTY與串口驅動程序 190
8.1 TTY概念 190
8.2 Linux TTY驅動程序體系 190
8.2.1 TTY驅動程序調用關系 190
8.2.2 TTY驅動程序原理 191
8.3 線路規程 194
8.4 串口驅動程序與TTY 196
8.4.1 串口設備驅動程序原理 196
8.4.2 S3C6410的串口驅動程序
實例 199
8.5 TTY應用層 202
第9章 網路設備驅動程序 205
9.1 DM9000網卡驅動程序
開發 205
9.1.1 DM9000原理 205
9.1.2 DM9000X驅動程序分析 207
9.1.3 DM9000網口驅動程序移植 215
9.2 NFS根文件系統搭建 219
9.2.1 主機配置 219
9.2.2 NFS根文件系統搭建實例 220
9.3 netlink Socket 224
9.3.1 netlink機制 224
9.3.2 netlink應用層編程 228
9.3.3 netlink驅動程序實例 229
第10章 framebuffer驅動程序 232
10.1 Linux framebuffer驅動
程序原理 232
10.1.1 framebuffer核心數據結構 232
10.1.2 framebuffer操作介面 234
10.1.3 framebuffer驅動程序的文件
介面 236
10.1.4 framebuffer驅動程序框架 236
10.2 S3C6410 顯示控制器 238
10.3 S3C6410 LCD驅動程序實例 243
10.4 framebuffer應用層 250
10.5 Qt4界面系統移植 251
第11章 輸入子系統驅動程序 253
11.1 Linux輸入子系統概述 253
11.1.1 input_dev結構 253
11.1.2 輸入事件 255
11.2 input_handler 256
11.2.1 Input Handler層 256
11.2.2 常用的Input Handler 259
11.3 輸入設備應用層 261
11.4 鍵盤輸入設備驅動程序
實例 262
11.5 event介面 267
11.6 觸摸屏驅動程序實例 270
11.6.1 S3C6410觸摸屏控制器 270
11.6.2 S3C6410觸摸屏驅動程序
設計 273
11.7 觸摸屏校準 282
11.7.1 觸摸屏校準原理 282
11.7.2 利用TSLIB庫校準觸摸屏 282
第12章 USB驅動程序 284
12.1 USB體系概述 284
12.1.1 USB系統組成 284
12.1.2 USB主機 284
12.1.3 USB設備邏輯層次 285
12.2 Linux USB驅動程序體系 287
12.2.1 USB總體結構 287
12.2.2 USB設備驅動程序 287
12.2.3 主機控制器驅動程序 288
12.2.4 USB請求塊urb 289
12.2.5 USB請求塊的填充 291
12.3 S3C6410 USB主機控制器
驅動程序 292
12.3.1 USB主機控制器驅動程序
分析 292
12.3.2 S3C6410 USB驅動程序
載入 294
12.4 USB鍵盤設備驅動程序
分析 296
12.5 USB Gadget驅動程序 301
12.5.1 Linux USB Gadget驅動程序 301
12.5.2 Linux USB Gadget驅動程序
實例 302
第13章 音頻設備驅動程序 303
13.1 ALSA音頻體系 303
13.2 ALSA驅動層API 304
13.2.1 音效卡和設備管理 304
13.2.2 PCM API 304
13.2.3 控制與混音API 305
13.2.4 AC97 API 306
13.2.5 SOC層驅動 307
13.3 ALSA驅動程序實例 308
13.3.1 S3C6410的AC97控制
單元 308
13.3.2 S3C6410音效卡電路原理 309
13.3.3 S3C6410的數字音頻介面 310
13.3.4 wm9713的數字音頻介面 313
13.4 ALSA音頻編程介面 316
13.4.1 ALSA PCM介面實例 316
13.4.2 ALSA MIDI介面實例 320
13.4.3 ALSA mixer介面實例 321
13.4.4 ALSA timer介面實例 322
第14章 video4linux2視頻
驅動程序 327
14.1 video4linux2驅動程序
架構 327
14.1.1 video4linux2驅動程序的
注冊 327
14.1.2 v4l2_fops介面 331
14.1.3 常用的結構 332
14.1.4 video4linux2的ioctl函數 333
14.2 S3C6410攝像頭驅動程序
分析 333
14.2.1 電路原理 333
14.2.2 驅動程序分析 334
14.3 video4linux2應用層實例 339
第15章 SD卡驅動程序 346
15.1 Linux SD卡驅動程序體系 346
15.1.1 SD卡電路原理 346
15.1.2 MMC卡驅動程序架構 347
15.1.3 MMC卡驅動程序相關
結構 347
15.1.4 MMC卡塊設備驅動程序 350
15.1.5 SD卡主機控制器介面驅動
程序 356
15.2 S3C6410 SD卡控制器驅動
程序分析 360
15.2.1 電路原理 360
15.2.2 S3C6410 SDHCI驅動
程序原理 360
15.2.3 SD卡的載入實例 364
參考文獻 366