內容簡介
本書由淺入深,全面、系統地介紹了linux驅動開發技術,提供了大量實例供讀者實戰演練。另外,作者在實例講解中詳細分析了各種重要的理論知識,讓讀者能夠舉一反三。
本書共分3篇。第1篇介紹了linux驅動開發概述、嵌入式處理器和開發板、構建嵌入式驅動程式開發環境、構建嵌入式linux作業系統、第一個驅動程式、簡單的字元設備驅動程式等內容;第2篇介紹了設備驅動中的並發控制、阻塞和同步機制、中斷與時鐘機制、記憶體訪問等內容;第3篇介紹了設備驅動模型、rtc實時時鐘驅動程式、看門狗驅動程式、iic設備驅動程式、lcd設備驅動程式、觸控螢幕設備驅動程式、輸入子系統驅動程式、塊設備驅動程式、usb設備驅動程式等內容。
作者專門為本書重點內容錄製了教學視頻,以提高讀者的學習效率。另外,本書還贈送了大量的linux拓展學習視頻。這些視頻和本書原始碼需要讀者自行下載,下載地址見封面提示。
本書重點突出,涉及面廣,實用性強,從基本知識到核心原理,再到實例開發,幾乎涉及linux驅動開發的所有重要知識。本書適合所有想學習linux驅動開發的入門人員閱讀,也適合作為驅動工程師的參考書,對於linux驅動開發的專業開發人員也有很高的參考價值。
目錄
第1篇 linux驅動開發基礎
第1章 linux驅動開發概述 2
1.1 linux設備驅動的基本概念 2
1.1.1 設備驅動程式概述 2
1.1.2 設備驅動程式的作用 2
1.1.3 設備驅動的分類 3
1.2 linux作業系統與驅動的關係 4
1.3 linux驅動程式開發 4
1.3.1 用戶態和核心態 5
1.3.2 模組機制 5
1.3.3 編寫設備驅動程式需要了解的知識 6
1.4 編寫設備驅動程式的注意事項 6
1.4.1 應用程式開發與驅動程式開發的差異 6
1.4.2 gun c開發驅動程式 7
1.4.3 不能使用c庫開發驅動程式 7
1.4.4 沒有記憶體保護機制 7
1.4.5 小核心棧 8
1.4.6 重視可移植性 8
1.5 linux驅動的發展趨勢 9
1.5.1 linux驅動的發展 9
.1.5.2 驅動的套用 9
1.5.3 相關學習資源 9
1.6 小結 10
第2章 嵌入式處理器和開發板簡介 11
2.1 處理器的選擇 11
2.1.1 處理器簡述 11
2.1.2 處理器的種類 11
2.2 arm處理器 13
2.2.1 arm處理器簡介 14
2.2.2 arm處理器系列 14
2.2.3 arm處理器的套用 16
2.2.4 arm處理器的選型 16
2.2.5 arm處理器選型舉例 19
2.3 s3c2440開發板 20
2.3.1 s3c2440開發板簡介 20
2.3.2 s3c2440開發板的特性 20
2.4 小結 22
第3章 構建嵌入式驅動程式開發環境 23
3.1 虛擬機和linux安裝 23
3.1.1 在windows上安裝虛擬機 23
3.1.2 在虛擬機上安裝linux 27
3.1.3 設定已分享資料夾 28
3.2 代碼閱讀工具source insight 29
3.2.1 source insight簡介 30
3.2.2 閱讀原始碼 30
3.3 小結 33
第4章 構建嵌入式linux作業系統 34
4.1 linux作業系統的介紹 34
4.1.1 linux作業系統 34
4.1.2 linux作業系統的優點 35
4.2 linux核心子系統 36
4.2.1 進程管理 36
4.2.2 記憶體管理 37
4.2.3 檔案系統 37
4.2.4 設備管理 37
4.2.5 網路功能 38
4.3 linux原始碼結構分析 38
4.3.1 arch目錄 38
4.3.2 drivers目錄 39
4.3.3 fs目錄 39
4.3.4 其他目錄 40
4.4 核心配置選項 41
4.4.1 配置編譯過程 41
4.4.2 常規配置 42
4.4.3 模組配置 44
4.4.4 塊設備層配置 44
4.4.5 cpu類型和特性配置 45
4.4.6 電源管理配置 47
4.4.7 匯流排配置 49
4.4.8 網路配置 50
4.4.9 設備驅動配置 53
4.4.10 檔案系統配置 60
4.5 嵌入式檔案系統基礎知識 62
4.5.1 嵌入式檔案系統 62
4.5.2 嵌入式系統的存儲介質 63
4.5.3 jffs檔案系統 64
4.5.4 yaffs檔案系統 64
4.6 構建根檔案系統 64
4.6.1 根檔案系統概述 65
4.6.2 linux根檔案系統目錄結構 65
4.6.3 busybox構建根檔案系統 66
4.7 小結 71
第5章 構建第一個驅動程式 72
5.1 開發環境配置之核心升級 72
5.1.1 為什麼升級核心 72
5.1.2 核心升級 73
5.1.3 make menconfig的注意事項 75
5.2 hello world驅動程式 77
5.2.1 驅動模組的組成 77
5.2.2 hello world模組 78
5.2.3 編譯hello world模組 79
5.2.4 模組的操作 81
5.2.5 hello world模組載入後檔案系統的變化 82
5.3 模組參數和模組之間通信 83
5.3.1 模組參數 83
5.3.2 模組的檔案格式elf 83
5.3.3 模組之間的通信 84
5.3.4 模組之間的通信實例 85
5.4 將模組加入核心 88
5.4.1 向核心添加模組 88
5.4.2 kconfig 88
5.4.3 kconfig的語法 89
5.4.4 套用實例:在核心中新增加add_sub模組 92
5.4.5 對add_sub模組進行配置 94
5.5 小結 95
第6章 簡單的字元設備驅動程式 96
6.1 字元設備驅動程式框架 96
6.1.1 字元設備和塊設備 96
6.1.2 主設備號和次設備號 97
6.1.3 申請和釋放設備號 98
6.2 初識cdev結構 99
6.2.1 cdev結構體 99
6.2.2 file_operations結構體 101
6.2.3 cdev和file_operations結構體的關係 102
6.2.4 inode結構體 103
6.3 字元設備驅動的組成 103
6.3.1 字元設備載入和卸載函式 103
6.3.2 file_operations結構體和其成員函式 104
6.3.3 驅動程式與應用程式的數據交換 105
6.3.4 字元設備驅動程式組成小結 106
6.4 virtualdisk字元設備驅動 106
6.4.1 virtualdisk的頭檔案、宏和設備結構體 106
6.4.2 載入和卸載驅動程式 107
6.4.3 cdev的初始化和註冊 108
6.4.4 打開和釋放函式 109
6.4.5 讀寫函式 110
6.4.6 seek()函式 111
6.4.7 ioctl()函式 113
6.5 小結 113
第2篇 linux驅動開發核心技術
第7章 設備驅動中的並發控制 116
7.1 並發與競爭 116
7.2 原子變數操作 116
7.2.1 原子變數操作 116
7.2.2 原子整型操作 117
7.2.3 原子位操作 119
7.3 自旋鎖 120
7.3.1 自旋鎖概述 120
7.3.2 自旋鎖的使用 120
7.3.3 自旋鎖的使用注意事項 122
7.4 信號量 122
7.4.1 信號量概述 122
7.4.2 信號量的實現 123
7.4.3 信號量的使用 123
7.4.4 自旋鎖與信號量的對比 125
7.5 完成量 126
7.5.1 完成量概述 126
7.5.2 完成量的實現 126
7.5.3 完成量的使用 127
7.6 小結 128
第8章 設備驅動中的阻塞和同步機制 129
8.1 阻塞和非阻塞 129
8.2 等待佇列 130
8.2.1 等待佇列概述 130
8.2.3 等待佇列的實現 130
8.2.3 等待佇列的使用 131
8.3 同步機制實驗 132
8.3.1 同步機制設計 132
8.3.2 實驗驗證 136
8.4 小結 137
第9章 中斷與時鐘機制 138
9.1 中斷簡述 138
9.1.1 中斷的概念 138
9.1.2 中斷的巨觀分類 139
9.1.3 中斷產生的位置分類 140
9.1.4 同步和異步中斷 140
9.1.5 中斷小結 140
9.2 中斷的實現過程 141
9.2.1 中斷信號線(irq) 141
9.2.2 中斷控制器 141
9.2.3 中斷處理過程 142
9.2.4 中斷的安裝與釋放 142
9.3 按鍵中斷實例 144
9.3.1 按鍵設備原理圖 144
9.3.2 有暫存器設備和無暫存器設備 144
9.3.3 按鍵設備相關連線埠暫存器 145
9.4 按鍵中斷實例程式分析 147
9.4.1 按鍵驅動程式組成 147
9.4.2 初始化函式s3c2440_buttons_init() 147
9.4.3 中斷處理函式isr_button() 148
9.4.4 退出函式s3c2440_buttons_exit() 149
9.5 時鐘機制 150
9.5.1 時間度量 150
9.5.2 時間延時 150
9.6 小結 151
第10章 內外存訪問 152
10.1 記憶體分配 152
10.1.1 kmalloc()函式 152
10.1.2 vmalloc()函式 153
10.1.3 後備高速快取 155
10.2 頁面分配 156
10.2.1 記憶體分配 156
10.2.2 物理地址和虛擬地址之間的轉換 159
10.3 設備i/o連線埠的訪問 160
10.3.1 linux i/o連線埠讀寫函式 160
10.3.2 i/o記憶體讀寫 160
10.3.3 使用i/o連線埠 164
10.4 小結 166
第3篇 linux驅動開發實用實戰
第11章 設備驅動模型 168
11.1 設備驅動模型概述 168
11.1.1 設備驅動模型的功能 168
11.1.2 sysfs檔案系統 169
11.1.3 sysfs檔案系統的目錄結構 170
11.2 設備驅動模型的核心數據結構 171
11.2.1 kobject結構體 171
11.2.2 設備屬性kobj_type 175
11.3 註冊kobject到sysfs中的實例 179
11.3.1 設備驅動模型結構 179
11.3.2 kset集合 180
11.3.3 kset與kobject的關係 181
11.3.4 kset相關的操作函式 182
11.3.5 註冊kobject到sysfs中的實例 183
11.3.6 實例測試 187
11.4 設備驅動模型的三大組件 188
11.4.1 匯流排 188
11.4.2 匯流排屬性和匯流排方法 192
11.4.3 設備 194
11.4.4 驅動 196
11.5 小結 198
第12章 rtc實時時鐘驅動 199
12.1 rtc實時時鐘硬體原理 199
12.1.1 rtc實時時鐘 199
12.1.2 rtc實時時鐘的功能 199
12.1.2 rtc實時時鐘的工作原理 201
12.2 rtc實時時鐘架構 205
12.2.1 載入卸載函式 205
12.2.2 rtc實時時鐘的平台驅動 206
12.2.3 rtc驅動探測函式 207
12.2.4 rtc實時時鐘的使能函式s3c_rtc_enable() 210
12.2.5 rtc實時時鐘設定頻率函式s3c_rtc_setfreq() 211
12.2.6 rtc設備註冊函式 rtc_device_register() 212
12.3 rtc檔案系統接口 214
12.3.1 檔案系統接口rtc_class_ops 214
12.3.2 rtc實時時鐘打開函式s3c_rtc_open() 215
12.3.3 rtc實時時鐘關閉函式s3c_rtc_release() 216
12.3.4 rtc實時時鐘獲得時間函式s3c_rtc_gettime() 216
12.3.5 rtc實時時鐘設定時間函式s3c_rtc_settime() 218
12.3.6 rtc驅動探測函式s3c_rtc_getalarm() 219
12.3.7 rtc實時時鐘設定報警時間函式s3c_rtc_setalarm() 220
12.3.8 rtc設定脈衝中斷使能函式s3c_rtc_setpie() 222
12.3.9 rtc時鐘脈衝中斷判斷函式s3c_rtc_proc() 222
12.4 小結 223
第13章 看門狗驅動程式 224
13.1 看門狗硬體原理 224
13.1.1 看門狗 224
13.1.2 看門狗工作原理 224
13.2 平台設備模型 226
13.2.1 平台設備模型 226
13.2.2 平台設備 227
13.2.3 平台設備驅動 229
13.2.4 平台設備驅動的註冊和註銷 230
13.2.5 混雜設備 231
13.2.6 混雜設備的註冊和註銷 232
13.3 看門狗設備驅動程式分析 232
13.3.1 看門狗驅動程式的一些變數定義 232
13.3.2 看門狗模組的載入和卸載函式 233
13.3.3 看門狗驅動程式探測函式 234
13.3.4 設定看門狗復位時間函式s3c2410wdt_set_heartbeat() 235
13.3.5 看門狗的開始函式s3c2410wdt_start()和停止函式
s3c2410wdt_ stop() 237
13.3.6 看門狗驅動程式移除函式s3c2410wdt_remove() 238
13.3.7 平台設備驅動s3c2410wdt_driver中的其他重要函式 238
13.3.8 混雜設備的file_operations中的函式 239
13.3.9 看門狗中斷處理函式s3c2410wdt_irq() 242
13.4 小結 243
第14章 iic設備驅動程式 244
14.1 iic設備的匯流排及其協定 244
14.1.1 iic匯流排的特點 244
14.1.2 iic匯流排的信號類型 245
14.1.3 iic匯流排的數據傳輸 245
14.2 iic設備的硬體原理 246
14.3 iic設備驅動程式的層次結構 247
14.3.1 iic設備驅動的概述 248
14.3.2 iic設備層 248
14.3.3 i2c_driver和i2c_client的關係 251
14.3.4 iic匯流排層 251
14.3.5 iic設備層和匯流排層的關係 253
14.3.6 寫iic設備驅動的步驟 253
14.4 iic子系統的初始化 254
14.4.1 iic子系統初始化函式i2c_init() 254
14.4.2 iic子系統退出函式i2c_exit () 254
14.5 適配器驅動程式 255
14.5.1 s3c2440對應的適配器結構體 255
14.5.2 iic適配器載入函式i2c_add_adapter() 257
14.5.3 idr機制 257
14.5.4 適配器卸載函式i2c_del_adapter() 260
14.5.5 iic匯流排通信方法s3c24xx_i2c_algorithm結構體 260
14.5.6 適配器的傳輸函式s3c24xx_i2c_doxfer() 262
14.5.7 適配器的中斷處理函式s3c24xx_i2c_irq() 265
14.5.8 位元組傳輸函式i2s_s3c_irq_nextbyte() 267
14.5.9 適配器傳輸停止函式s3c24xx_i2c_stop() 269
14.5.10 中斷處理函式的一些輔助函式 270
14.6 iic設備層驅動程式 270
14.6.1 iic設備驅動模組載入和卸載 271
14.6.2 探測函式s3c24xx_i2c_probe() 272
14.6.3 移除函式s3c24xx_i2c_remove() 274
14.6.4 控制器初始化函式s3c24xx_i2c_init() 275
14.6.5 設定控制器數據傳送頻率函式s3c24xx_i2c_clockrate() 276
14.7 小結 278
第15章 lcd設備驅動程式 279
15.1 framebuffer概述 279
15.1.1 framebuffer的概念 279
15.1.2 framebuffer與應用程式的互動 280
15.1.3 framebuffer顯示原理 280
15.1.4 lcd顯示原理 281
15.2 framebuffer的結構分析 281
15.2.1 framebuffer架構和其關係 281
15.2.2 framebuffer驅動程式的實現 282
15.2.3 framebuffer架構及其關係 283
15.3 lcd驅動程式分析 288
15.3.1 lcd模組的載入和卸載函式 288
15.3.2 lcd驅動程式的平台數據 290
15.3.3 lcd模組的探測函式 291
15.3.4 移除函式 295
15.4 小結 296
第16章 觸控螢幕設備驅動程式 297
16.1 觸控螢幕設備工作原理 297
16.1.1 觸控螢幕設備概述 297
16.1.2 觸控螢幕設備的類型 297
16.1.3 電阻式觸控螢幕 298
16.2 觸控螢幕設備硬體結構 298
16.2.1 s3c2440觸控螢幕接口概述 298
16.2.2 s3c2440觸控螢幕接口的工作模式 299
16.2.3 s3c2440觸控螢幕設備暫存器 300
16.3 觸控螢幕設備驅動程式分析 303
16.3.1 觸控螢幕設備驅動程式組成 303
16.3.2 s3c2440觸控螢幕驅動模組的載入和卸載函式 304
16.3.3 s3c2440觸控螢幕驅動模組的探測函式 305
16.3.4 觸控螢幕設備配置 308
16.3.5 觸控螢幕設備中斷處理函式 309
16.3.6 s3c2440觸控螢幕驅動模組的remove()函式 314
16.4 測試觸控螢幕驅動程式 314
16.5 小結 316
第17章 輸入子系統設計 317
17.1 input子系統入門 317
17.1.1 簡單的實例 317
17.1.2 註冊函式input_register_device() 319
17.1.3 向子系統報告事件 323
17.2 handler註冊分析 328
17.2.1 輸入子系統的組成 328
17.2.2 input_handler結構體 328
17.2.3 註冊input_handler 329
17.2.4 input_handle結構體 330
17.2.5 註冊input_handle 331
17.3 input子系統 332
17.3.1 子系統初始化函式input_init() 333
17.3.2 檔案打開函式input_open_file() 333
17.4 evdev輸入事件驅動分析 335
17.4.1 evdev的初始化 335
17.4.2 evdev設備的打開 337
17.5 小結 340
第18章 塊設備驅動程式 341
18.1 塊設備簡介 341
18.1.1 塊設備總體概述 341
18.1.2 塊設備的結構 342
18.2 塊設備驅動程式的架構 344
18.2.1 塊設備載入過程 344
18.2.2 塊設備卸載過程 345
18.3 通用塊層 346
18.3.1 通用塊層 346
18.3.2 alloc_disk()函式對應的gendisk結構體 346
18.3.3 塊設備的註冊和註銷 349
18.3.4 請求佇列 349
18.3.5 設定gendisk屬性中的block_device_operations結構體 350
18.4 不使用請求佇列的塊設備驅動 351
18.4.1 不使用請求佇列的塊設備驅動程式的組成 352
18.4.2 宏定義和全局變數 352
18.4.3 載入函式 353
18.4.4 卸載函式 355
18.4.5 自定義請求處理函式 355
18.4.6 驅動的測試 356
18.5 i/o調度器 359
18.5.1 數據從記憶體到磁碟的過程 359
18.5.2 塊i/o請求(bio) 360
18.5.3 請求結構(request) 363
18.5.4 請求佇列(request_queue) 364
18.5.5 請求佇列、請求結構、bio等之間的關係 365
18.5.6 四種調度算法 365
18.6 自定義i/o調度器 367
18.6.1 virtual_blkdev塊設備的缺陷 367
18.6.2 指定noop調度器 368
18.6.3 virtual_blkdev的改進實例 368
18.6.4 編譯和測試 369
18.7 脫離i/o調度器 370
18.7.1 請求佇列中的bio處理函式 370
18.7.2 通用塊層函式調用關係 371
18.7.3 對virtual_blkdev塊設備的改進 373
18.7.4 編譯和測試 376
18.8 塊設備的物理結構 377
18.8.1 為virtual_blkdev塊設備添加分區 377
18.8.2 對新的virtual_blkdev代碼的分析 378
18.8.3 編譯和測試 379
18.8.4 分區數的計算 381
18.8.5 設定virtual_blkdev的結構 382
18.8.6 編譯和測試 384
18.9 小結 387
第19章 usb設備驅動程式 389
19.1 usb概述 389
19.1.1 usb概念 389
19.1.2 usb的特點 390
19.1.3 usb匯流排拓撲結構 391
19.1.4 usb驅動總體架構 391
19.2 usb設備驅動模型 395
19.2.1 usb驅動初探 395
19.2.2 usb設備驅動模型 397
19.2.3 usb驅動結構usb_driver 399
19.3 usb設備驅動程式 404
19.3.1 usb設備驅動載入和卸載函式 404
19.3.2 探測函式probe()的參數usb_interface 405
19.3.3 usb協定中的設備 406
19.3.4 端點的傳輸方式 412
19.3.5 設定 413
19.3.6 探測函式storage_probe() 415
19.4 獲得usb設備信息 418
19.4.1 設備關聯函式associate_dev() 418
19.4.2 獲得設備信息函式get_device_info() 419
19.4.3 得到傳輸協定get_transport()函式 420
19.4.4 獲得協定信息函式get_protocol() 421
19.4.5 獲得管道信息函式get_pipes() 422
19.5 資源的初始化 425
19.5.1 storage_probe()函式調用過程 425
19.5.2 資源獲取函式usb_stor_acquire_resources() 426
19.5.3 usb請求塊(urb) 427
19.6 控制子執行緒 430
19.6.1 控制執行緒 431
19.6.2 掃描執行緒usb_stor_scan_thread() 433
19.6.3 獲得lun函式usb_stor_bulk_max_lun() 434
19.7 小結 441