本書講解了Linux驅(qū)動開發(fā)的基礎(chǔ)知識以及所用到的開發(fā)環(huán)境,全書分為22章,其內(nèi)容涵蓋了各種Linux子系統(tǒng),包含內(nèi)存管理、PWM、RTC、IIO和IRQ管理等,還講解了直接內(nèi)存訪問和網(wǎng)絡(luò)設(shè)備驅(qū)動程序的實用方法。在學完本書之后,讀者將掌握設(shè)備驅(qū)動開發(fā)環(huán)境的概念,并可以從零開始為任何硬件設(shè)備編寫驅(qū)動程序。
閱讀本書需要具備基本的C語言程序設(shè)計能力,且熟悉Linux基本命令。本書主要是為嵌入式工程師、Linux系統(tǒng)管理員、開發(fā)人員和內(nèi)核黑客而設(shè)計的。無論是軟件開發(fā)人員,還是系統(tǒng)架構(gòu)師或制造商,只要愿意深入研究Linux驅(qū)動程序開發(fā),閱讀本書后都將有所收獲。
1.本書將幫助您了解驅(qū)動程序的基礎(chǔ)知識,并為漫長的Linux內(nèi)核之旅做好準備。
2.本書介紹了基于各種Linux子系統(tǒng)的驅(qū)動程序開發(fā),例如內(nèi)存管理、PWM、RTC、IIO和IRQ管理。
3.本書還提供了有關(guān)直接內(nèi)存訪問和網(wǎng)絡(luò)設(shè)備驅(qū)動程序的實用方法。
4.通過閱讀本書,您將掌握設(shè)備驅(qū)動程序開發(fā)的概念,并將能夠使用最新的內(nèi)核版本(編寫本書時為v4.13)從頭編寫任何設(shè)備驅(qū)動程序。
5.提供源代碼。
Linux內(nèi)核是一個復雜、可移植、模塊化且使用廣泛的軟件,其可在設(shè)備的服務器和嵌入式系統(tǒng)上運行。設(shè)備驅(qū)動程序在Linux系統(tǒng)的性能方面起著至關(guān)重要的作用。由于Linux已經(jīng)成為非常受歡迎的操作系統(tǒng),因此開發(fā)專有設(shè)備驅(qū)動程序的需求也在穩(wěn)步增長。
您將學到以下內(nèi)容:
·使用內(nèi)核工具開發(fā)功能強大的驅(qū)動程序;
·為I2C和SPI設(shè)備開發(fā)驅(qū)動程序,并使用Regmap API;
·在驅(qū)動程序內(nèi)編寫和支持設(shè)備樹;
·為網(wǎng)絡(luò)和幀緩沖設(shè)備編寫高級驅(qū)動程序;
·深入研究Linux irqdomain API并編寫中斷控制器驅(qū)動程序;
·通過調(diào)節(jié)器和PWM框架增強技能;
·使用IIO框架開發(fā)測量系統(tǒng)驅(qū)動程序;
·充分利用內(nèi)存管理和DMA子系統(tǒng);
·訪問和管理GPIO子系統(tǒng)并開發(fā)GPIO控制器驅(qū)動程序。
John Madieu是嵌入式Linux和內(nèi)核研發(fā)工程師,居住在法國巴黎。他主要為自動化、運輸、醫(yī)療、能源和軍事等領(lǐng)域的公司開發(fā)驅(qū)動程序和開發(fā)板支持包(Board Support Packages,BSP)。他目前就職于一家法國公司EXPEMB,該公司是基于模塊化計算機的電子開發(fā)板設(shè)計和嵌入式Linux解決方案的先驅(qū)。同時,他還是一位開源和嵌入式系統(tǒng)愛好者,堅信通過知識分享能夠?qū)W到更多的知識。
第 1章 內(nèi)核開發(fā)簡介 1
1.1 環(huán)境設(shè)置 1
1.1.1 獲取源代碼 2
1.1.2 內(nèi)核配置 4
1.1.3 構(gòu)建自己的內(nèi)核 4
1.2 內(nèi)核約定 6
1.2.1 編碼風格 6
1.2.2 內(nèi)核結(jié)構(gòu)分配和初始化 7
1.2.3 類、對象、面向?qū)ο蟮木幊獭?
1.3 總結(jié) 8
第 2章 設(shè)備驅(qū)動程序基礎(chǔ) 9
2.1 內(nèi)核空間和用戶空間 9
2.1.1 模塊的概念 10
2.1.2 模塊依賴 10
2.1.3 模塊的加載和卸載 11
2.2 驅(qū)動程序框架 13
2.2.1 模塊的入點和出點 14
2.2.2 模塊信息 16
2.3 錯誤和消息打印 18
2.3.1 錯誤處理 19
2.3.2 處理空指針錯誤 21
2.3.3 消息打印—— printk() 22
2.4 模塊參數(shù) 24
2.5 構(gòu)建第 一個模塊 25
2.5.1 模塊的makefile 26
2.5.2 內(nèi)核樹內(nèi) 27
2.5.3 內(nèi)核樹外 29
2.5.4 構(gòu)建模塊 29
2.6 總結(jié) 30
第3章 內(nèi)核工具和輔助函數(shù) 31
3.1 理解宏container_of 31
3.2 鏈表 33
3.2.1 創(chuàng)建和初始化鏈表 35
3.2.2 創(chuàng)建鏈表節(jié)點 36
3.2.3 添加鏈表節(jié)點 36
3.2.4 刪除鏈表節(jié)點 37
3.2.5 鏈表遍歷 37
3.3 內(nèi)核的睡眠機制 38
3.4 延遲和定時器管理 41
3.4.1 標準定時器 41
3.4.2 高精度定時器(HRT) 44
3.4.3 動態(tài)Tick/Tickless內(nèi)核 46
3.4.4 內(nèi)核中的延遲和睡眠 46
3.5 內(nèi)核的鎖機制 47
3.5.1 互斥鎖 47
3.5.2 自旋鎖 49
3.6 工作延遲機制 51
3.6.1 Softirq和Ksoftirqd 51
3.6.2 Tasklet 53
3.6.3 Tasklet調(diào)度 54
3.6.4 工作隊列 56
3.6.5 內(nèi)核線程 62
3.7 內(nèi)核中斷機制 62
3.7.1 注冊中斷處理程序 62
3.7.2 下半部的概念 65
3.8 線程化中斷 68
3.9 從內(nèi)核調(diào)用用戶空間應用程序 71
3.10 總結(jié) 72
第4章 字符設(shè)備驅(qū)動程序 73
4.1 主設(shè)備和次設(shè)備的概念 73
4.2 設(shè)備文件操作 76
4.3 分配和注冊字符設(shè)備 77
4.4 寫文件操作 79
4.4.1 內(nèi)核空間和用戶空間數(shù)據(jù)交換 79
4.4.2 open方法 80
4.4.3 release方法 81
4.4.4 write方法 82
4.4.5 read方法 84
4.4.6 llseek方法 86
4.4.7 poll方法 88
4.4.8 ioctl方法 91
4.4.9 填充file_operations結(jié)構(gòu) 95
4.5 總結(jié) 95
第5章 平臺設(shè)備驅(qū)動程序 96
5.1 平臺驅(qū)動程序 97
5.2 平臺設(shè)備 100
5.3 設(shè)備、驅(qū)動程序和總線匹配 105
5.4 總結(jié) 113
第6章 設(shè)備樹的概念 114
6.1 設(shè)備樹機制 114
6.1.1 命名約定 115
6.1.2 別名、標簽和phandle 115
6.1.3 DT編譯器 117
6.2 表示和尋址設(shè)備 117
6.2.1 SPI和I2C尋址 118
6.2.2 平臺設(shè)備尋址 119
6.3 處理資源 120
6.3.1 命名資源的概念 121
6.3.2 訪問寄存器 122
6.3.3 處理中斷 123
6.3.4 提取特定應用數(shù)據(jù) 124
6.4 平臺驅(qū)動程序和DT 127
6.4.1 OF匹配風格 127
6.4.2 匹配風格混合 132
6.4.3 平臺數(shù)據(jù)與DT 136
6.5 總結(jié) 137
第7章 I2C客戶端驅(qū)動程序 138
7.1 驅(qū)動程序架構(gòu) 139
7.1.1 i2c_driver結(jié)構(gòu) 139
7.1.2 驅(qū)動程序的初始化和注冊 142
7.1.3 驅(qū)動程序和設(shè)備的配置 142
7.2 訪問客戶端 143
7.2.1 普通I2C通信 143
7.2.2 系統(tǒng)管理總線(SMBus)兼容函數(shù) 145
7.2.3 在開發(fā)板配置文件中實例化I2C設(shè)備(棄用的舊方式) 146
7.3 I2C和設(shè)備樹 147
7.3.1 定義和注冊I2C驅(qū)動程序 147
7.3.2 在設(shè)備樹中實例化I2C設(shè)備——新方法 149
7.3.3 小結(jié) 149
7.4 總結(jié) 150
第8章 SPI設(shè)備驅(qū)動程序 151
8.1 驅(qū)動程序架構(gòu) 151
8.1.1 設(shè)備結(jié)構(gòu) 152
8.1.2 spi_driver結(jié)構(gòu) 154
8.1.3 驅(qū)動程序的初始化和注冊 156
8.1.4 驅(qū)動程序和設(shè)備配置 157
8.2 訪問和與客戶端通信 161
8.3 小結(jié) 166
8.4 SPI用戶模式驅(qū)動程序 166
8.5 總結(jié) 170
第9章 Regmap API ——寄存器映射抽象 171
9.1 使用Regmap API編程 172
9.1.1 regmap_config結(jié)構(gòu) 172
9.1.2 Regmap初始化 175
9.1.3 設(shè)備訪問函數(shù) 177
9.1.4 Regmap和緩存 180
9.1.5 小結(jié) 181
9.1.6 Regmap示例 182
9.2 總結(jié) 184
第 10章 IIO框架 185
10.1 IIO數(shù)據(jù)結(jié)構(gòu) 186
10.1.1 Iio_dev數(shù)據(jù)結(jié)構(gòu) 186
10.1.2 iio_info結(jié)構(gòu) 190
10.1.3 IIO通道 190
10.1.4 小結(jié) 196
10.2 觸發(fā)緩沖區(qū)支持 199
10.2.1 IIO觸發(fā)器和sysfs(用戶空間) 202
10.2.2 IIO緩沖區(qū) 206
10.2.3 小結(jié) 208
10.3 IIO數(shù)據(jù)訪問 214
10.3.1 單次捕獲 214
10.3.2 緩沖區(qū)數(shù)據(jù)訪問 214
10.4 IIO工具 216
10.5 總結(jié) 217
第 11章 內(nèi)核內(nèi)存管理 218
11.1 系統(tǒng)內(nèi)存布局——內(nèi)核空間和用戶空間 219
11.1.1 內(nèi)核地址——低端和高端內(nèi)存概念 221
11.1.2 用戶空間尋址 222
11.1.3 虛擬內(nèi)存區(qū)域 225
11.2 地址轉(zhuǎn)換和MMU 227
11.3 內(nèi)存分配機制 232
11.3.1 頁面分配器 233
11.3.2 Slab分配器 235
11.3.3 kmalloc分配系列 238
11.3.4 vmalloc分配器 240
11.3.5 后臺的進程內(nèi)存分配 242
11.4 使用I/O內(nèi)存訪問硬件 244
11.4.1 PIO設(shè)備訪問 244
11.4.2 MMIO設(shè)備訪問 245
11.5 內(nèi)存(重)映射 248
11.5.1 kmap 248
11.5.2 映射內(nèi)核內(nèi)存到用戶空間 249
11.6 Linux緩存系統(tǒng) 253
11.6.1 什么是緩存 253
11.6.2 為什么數(shù)據(jù)延遲寫入磁盤 255
11.7 設(shè)備管理的資源—— Devres 256
11.8 總結(jié) 257
第 12章 DMA ——直接內(nèi)存訪問 258
12.1 設(shè)置DMA映射 258
12.1.1 緩存一致性和DMA 258
12.1.2 DMA映射 259
12.2 完成的概念 263
12.3 DMA引擎API 264
12.3.1 分配DMA從通道 265
12.3.2 設(shè)置從設(shè)備和控制器指定參數(shù) 266
12.3.3 獲取事務描述符 269
12.3.4 提交事務 270
12.3.5 發(fā)布待處理DMA請求并等待回調(diào)通知 271
12.4 總結(jié)—— NXP SDMA(i.MX6) 272
12.5 DMA DT綁定 277
12.6 總結(jié) 278
第 13章 Linux設(shè)備模型 279
13.1 LDM數(shù)據(jù)結(jié)構(gòu) 279
13.1.1 總線 280
13.1.2 設(shè)備驅(qū)動程序 285
13.1.3 設(shè)備 287
13.2 深入剖析LDM 289
13.2.1 kobject結(jié)構(gòu) 289
13.2.2 kobj_type 291
13.2.3 內(nèi)核對象集合 293
13.2.4 屬性 294
13.3 設(shè)備模型和sysfs 296
13.3.1 sysfs文件和屬性 297
13.3.2 允許輪詢sysfs屬性文件 303
13.4 總結(jié) 304
第 14章 引腳控制和GPIO子系統(tǒng) 305
14.1 引腳控制子系統(tǒng) 305
14.2 GPIO子系統(tǒng) 310
14.2.1 基于整數(shù)的GPIO接口:傳統(tǒng)方法 310
14.2.2 基于描述符的GPIO接口:新的推薦方式 315
14.2.3 GPIO接口和設(shè)備樹 322
14.2.4 GPIO和sysfs 327
14.3 總結(jié) 329
第 15章 GPIO控制器驅(qū)動程序—— gpio_chip 330
15.1 驅(qū)動程序體系結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu) 330
15.2 引腳控制器指南 334
15.3 GPIO控制器的sysfs接口 335
15.4 GPIO控制器和DT 335
15.5 總結(jié) 336
第 16章 高級IRQ管理 337
16.1 中斷復用和中斷控制器 339
16.2 高級外設(shè)IRQ管理 347
16.3 中斷請求和傳播 349
16.3.1 鏈接IRQ 351
16.3.2 案例研究—— GPIO和IRQ芯片 351
16.4 總結(jié) 356
第 17章 輸入設(shè)備驅(qū)動程序 357
17.1 輸入設(shè)備結(jié)構(gòu) 357
17.2 分配并注冊輸入設(shè)備 360
17.3 產(chǎn)生和報告輸入事件 364
17.4 用戶空間接口 366
17.5 回顧 368
17.6 總結(jié) 376
第 18章 RTC驅(qū)動程序 377
18.1 RTC框架數(shù)據(jù)結(jié)構(gòu) 377
18.2 RTC和用戶空間 387
18.2.1 sysfs接口 387
18.2.2 hwclock工具 388
18.3 總結(jié) 389
第 19章 PWM驅(qū)動程序 390
19.1 PWM控制器驅(qū)動程序 391
19.1.1 驅(qū)動程序示例 393
19.1.2 PWM控制器綁定 396
19.2 PWM消費者接口 397
19.3 通過sysfs接口使用PWM 401
19.4 總結(jié) 402
第 20章 調(diào)節(jié)器框架 403
20.1 PMIC/生產(chǎn)者驅(qū)動程序接口 404
20.1.1 驅(qū)動程序數(shù)據(jù)結(jié)構(gòu) 404
20.1.2 驅(qū)動程序方法 412
20.1.3 驅(qū)動程序示例 418
20.2 調(diào)節(jié)器消費者接口 421
20.2.1 調(diào)節(jié)器設(shè)備請求 422
20.2.2 控制調(diào)節(jié)器設(shè)備 423
20.3 調(diào)節(jié)器綁定 425
20.4 總結(jié) 426
第 21章 幀緩沖驅(qū)動程序 427
21.1 驅(qū)動程序數(shù)據(jù)結(jié)構(gòu) 428
21.2 設(shè)備方法 431
21.3 驅(qū)動程序方法 434
21.3.1 fb_ops剖析 436
21.3.2 總結(jié) 440
21.4 用戶空間的幀緩沖 440
21.5 總結(jié) 442
第 22章 網(wǎng)絡(luò)接口卡驅(qū)動程序 443
22.1 驅(qū)動程序數(shù)據(jù)結(jié)構(gòu) 443
22.1.1 套接字緩沖區(qū)結(jié)構(gòu) 444
22.1.2 網(wǎng)絡(luò)接口結(jié)構(gòu) 446
22.2 設(shè)備方法 448
22.2.1 打開和關(guān)閉 449
22.2.2 數(shù)據(jù)包處理 452
22.2.3 驅(qū)動程序示例 457
22.2.4 狀態(tài)和控制 460
22.3 驅(qū)動程序方法 463
22.3.1 probe函數(shù) 464
22.3.2 模塊卸載 466
22.4 總結(jié) 466