筆記本電腦的內置鍵盤是不可缺少的輸入設備,它經歷了二十幾年的迭代才形成如今的設計標準(Key Layout、Connector、Protocol、ScanCode...)。
在鍵盤的發展歷程中,出現了很多標準,有一些標準至今仍被使用。有興趣可以查閱 鍵盤的發展。接下來就詳細了解下筆記本電腦的鍵盤。
01—Scan Code
電腦鍵盤一般有 80-120 個按鍵,因此采用矩陣設計可以減少GPIO 的使用。
如下示意圖,MCU 控制 “A/B/C/D” 都保持低電平,然后挨個輸出高電平,每次輸出高電平的同時采集“1/2/3/4” 電平。此過程稱之為 “鍵盤掃描”。
如果 C-3 按鍵按下,當 MCU 在 “C” 列輸出高電平時,在 “3” 行可檢測到高電平。如此 MCU 即可判斷出哪個按鍵被按下了。
MCU 判斷出哪個按鍵被按下,需要以數據的形式傳遞給 Host 使用。因此需要給每一個按鍵安排一個編碼,這個編碼就是 ScanCode,即 “掃描碼”。
這個 MCU 負責掃描矩陣,稱之為 KSC(Keyboard Scan Controller)。使用最為廣泛的型號是 Intel 8048。
鍵盤的發展歷程中,一共出現過 3 套 ScanCode。
Scan Code Set-1
1983年隨 IBM Personal Computer XT(XT:eXtended Technology,Type:5160) 一起發布的 XT Keyboard 就使用的是此套掃描碼。當時配套的操作系統可以直接識別此套掃描碼。如今的 Windows、Linux 系統都在沿用。
ScanCode Set-2
1984年隨 IBM Personal Computer AT(AT:Advanced Technology,Type:5170)一起發布的 AT Keyboard 就是使用的是此套掃描碼。但是操作系統并沒有兼容識別此套掃描碼,而是在主板上增加了一個 MCU 把 Set-2 翻譯成 Set-1,然后再發送給系統。當然也有操作系統也可以識別 Set-2,但并不是主流。
新增的 MCU 稱之為 KBC(Keyboard Controller),使用最為廣泛的型號是 Intel 8042,因此 i8042 也用來代指 Keyboard Controller。
ScanCode Set-3
1986年,IBM 重新設計了鍵盤布局,在美國市場上推出了 MF2 Keyboard,有 101個按鍵。
MF2 Keyboard 設計上增加了邏輯更為合理的 ScanCode Set-3,由 i8042 翻譯成 ScanCode Set-1 傳遞給 CPU。此套掃描碼并未流行。
最后流行的 PS/2 鍵盤,采用的仍舊是 ScanCode Set-2。
02—Key Number
在 MF2 鍵盤出現后,鍵盤 Layout 基本即保持一致了,但是按鍵的絲印卻是千變萬化,不同絲印的鍵盤是為了滿足不同語種的需求。
鍵盤設計中,一個按鍵會規定一個 ScanCode。系統端根據接收的 ScanCode 就知道是哪個按鍵觸發了。同樣是按鍵 “Q” 觸發,系統端最終識別的字符可不一定是字符 “Q”,這是要根據系統語言判斷的。
鍵盤語種不同,絲印就不同。因此每個按鍵還規定了一個 Key Number,以便區分按鍵。
一般鍵盤制造商生產的矩陣鍵盤,會配套一份設計圖紙,會指明按鍵在矩陣中的位置,此時使用的就是 KeyNumber。
KSC 掃描這個矩陣,根據掃描結果,識別出觸發按鍵在矩陣的位置,
先找到 KeyNumber,從而查找出 ScanCode。
03—Keyboard Protocol
XT Keyboard 和 AT Keyboard 的設計中,同 PCH 通訊的規范已經不再使用,因此此處只針對 PS/2 Keyboard 做描述。
PS/2 Keyboard 設計中,采用 KSC (Keyboard Scan Controller) 掃描鍵盤矩陣,按鍵觸發后會編碼出 ScanCode Set-2 發送。其中 KSC 是一個位于鍵盤內部的 MCU,以 Intel 8048 最為典型。KSC 和 KBC 之間通過 PS/2 協議通訊,完成KeyCode、Command 的傳遞。
PS/2 鍵盤結構
在 x86 CPU 系統中,有一個獨立的 IO 尋址空間,大小 64K。隨著計算機的發展,默認 60/64 兩個 IO 地址被用作 PCH 和 KBC(i8042) 交換數據。
有以上兩個通訊的支持, PS/2 Keyboard 外接在電腦 PS/2 接口上后就可以工作了。
設計框圖如下
KBC 寄存器
i8042 作為一個 KBC 使用 IO 60、64 和 PCH 傳遞數據。
IO 60/64 分別定義為數據寄存器和狀態寄存器。
針對 Status Register,在 Intel 8042 DataSheet 中定義如下。
BIT0:指示 KBC 是否在 Output Data Register 寫入了數據。
BIT1:指示 CPU 是否在 Input Data Register 寫入了數據。
BIT2:指示 CPU 是否讀取了 Output Register。
BIT3:指示 CPU 寫了 60H 還是 64H。
BIT4-7:用戶自定義。
不同廠家在后續的 KBC 設計中,增加了一些自定義狀態。
如下圖所示,KBC 中增加了針對 PS/2 通訊狀態的一些定義。
如上圖,Host 端的 Keyboard Driver 利用 IO 60/64 和 KBC通訊。
KBC 內部有兩個數據寄存器,Input and Output Data Register。
一個狀態寄存器,Status Register。
KB Driver 寫 60H 或者 64H,都對應 KBC 內部 Input Register,KBC 內部的 Status Register BIT3 會做出區分。
KB Driver 寫 60H,KBC 認為是 Data。
KB Driver 寫 64H,KBC 認為是自己的 Command。
KB Driver 讀 60H,KBC 返回 Output Register 內容,主要是 ScanCode。
KB Driver 讀 64H,KBC 返回 Status Register 內容,指示 Keyboard 狀態。
04—Keyboard Command
KBC 和 KSC 作為 MCU,分別設計了一組命令。Keyboard Driver 可以發送這些命令,從而控制 KBC 和 KSC 的一些行為。
05—EC Keyboard
在上世紀的個人電腦設計中,PS/2 鍵盤屬于一個外接設備。PS/2 鍵盤通過 PS/2 接口和主板上 KBC 通訊。KBC 在 PCH 和鍵盤中間作為一個 SuperIO 設備,管理 PS/2 鍵盤。
隨著個人電腦的不斷發展,逐漸演變出便攜式電腦,即筆記本電腦。鍵盤作為筆記本電腦的標配輸入設備,也遵守了 PS/2 鍵盤系統的大部分標準,并且沿用至今。
在如今的筆記本電腦設計中,不再有獨立的 KSC(i8048,鍵盤掃描器)和 KBC(i8042,鍵盤控制器),因此也不再有 PS/2 接口和 PS/2 協議存在。
KSC 和 KBC 的功能全部集成在一個專用 MCU 中,即集成在 EC 中。
EC 作為一個專用 MCU,設計有 8*18 的鍵盤掃描模塊,實現矩陣鍵盤的掃描。EC 也設計有 LPC 總線,和 PCH 實現 IO 6064 通訊。因此在 EC 固件中即可實現 KBC 功能。
EC 這顆專用 MCU 集成了原先 KBC 的功能,因此 EC 也會叫 KBC。
如今筆記本電腦中,EC 鍵盤系統設計框圖如下:
06—Keyboard Init
EC 鍵盤的實際工作原理和 PS/2 鍵盤基本一致,其中的 KBC 需要被 Host 端 Driver 初始化后,才能正常工作。
KBC 由 EC 固件實現,因此上述 KBC、KSC 相關的指令必須由 EC 固件實現,并且返回正確的值,否則 OS 端 KB Driver 初始化無法完成,會導致Windows 系統下設備管理器中 PS/2 設備出現黃色感嘆號,鍵盤無法使用。
UEFI 環境下,KBC 初始化。
EC 固件實現了 KBC 邏輯后,添加必要的 log后,當 UEFI 環境啟動后會對 KBC 初始化。EC 端 log 如下圖:
上圖是在 EC 中記錄了進入 UEFI Shell 環境時的鍵盤初始化序列。
通訊 | 釋義 | |
---|---|---|
1 | Host->EC, i8042 cmd[AD] | 8042 command Disable Keyboard |
2 | Host->EC, i8042 cmd[A7] | 8042 command Disable Mouse |
3 | Host->EC, i8042 cmd[AA] | 8042 command Self Test |
4 | EC->Host, data=[55] | EC Response test results |
5 | Host->EC, i8042 cmd[60] | 8042 command Write controller config byte |
6 | Host->EC, i8042 data[67] | controller config byte is 0x67 |
7 | Host->EC, i8042 data[F4] | Send to IO_60 without command |
8 | Host->EC, i8048 cmd[F4] | 8048 command Enable matrix scan |
9 | EC->Host, data=[FA] | EC send “ACK”,must 0xFA |
10 | Host->EC, i8042 cmd[AB] | 8042 command Keyboard interface test |
11 | EC->Host, data=[00] | EC Response test results,must 00 |
12 | Host->EC, i8042 data[FF] | Send to IO_60 without command |
13 | Host->EC, i8048 cmd[FF] | 8048 command Reset and start self-test |
14 | EC->Host, data=[FA] | EC send “ACK”,must 0xFA |
15 | EC->Host, data=[AA] | EC Response test results |
17 | Host->EC, i8042 data[F0] | Send to IO_60 without command |
18 | Host->EC, i8048 cmd[F0] | 8048 command Get/set current scan code set |
19 | EC->Host, data=[FA] | EC send “ACK”,must 0xFA |
20 | Host->EC, i8042 data[02] | Send to IO_60 without command |
21 | Host->EC, i8048 cmd[02] | 8048 sub-command select scancode set-2 |
22 | EC->Host, data=[FA] | EC send “ACK”,must 0xFA |
23 | Host->EC, i8042 data[F4] | Send to IO_60 without command |
24 | Host->EC, i8048 cmd[F4] | 8048 command Enable matrix scan |
25 | EC->Host, data=[FA] | EC send “ACK”,must 0xFA |
26 | Host->EC, i8042 data[ED] | Send to IO_60 without command |
27 | Host->EC, i8048 cmd[ED] | 8048 command control LED status |
28 | EC->Host, data=[FA] | EC send “ACK”,must 0xFA |
29 | Host->EC, i8042 data[00] | Send to IO_60 without command |
30 | Host->EC, i8048 cmd[00] | 8048 set LED off |
31 | EC->Host, data=[FA] | EC send “ACK”,must 0xFA |
上述初始化過程在如下文件中可以找到:
UDK2018/IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
OS 環境下,KBC 初始化。
Windows 或者 Linux 系統在加載過程中,BIOS 聲明了 PS/2 鍵盤設備后,OS 內置的 PS/2 Keyboard Driver 就會加載,完成 EC 內 KBC 和 KSC 的初始化,以及配置。當然 Windows Inbox PS/2 Driver 看不到源碼,感興趣的話可以看看 Linux PS/2 Driver 的源碼。
需要注意的是,UEFI 和 OS 下 KBC 初始化流程基本一致。
差異點是,UEFI 環境下 CPU 不響應 SERIRQ 中的 IRQ-1,靠輪詢的方式工作。OS下 CPU 需要響應 IRQ-1,當有鍵盤中斷觸發后,Driver 才會被回調,處理 IO 60/64 的數據。
-
mcu
+關注
關注
146文章
17148瀏覽量
351197 -
筆記本電腦
+關注
關注
9文章
1408瀏覽量
48186 -
鍵盤
+關注
關注
4文章
859瀏覽量
39669 -
電腦鍵盤
+關注
關注
0文章
14瀏覽量
12282 -
GPIO
+關注
關注
16文章
1204瀏覽量
52098
發布評論請先 登錄
相關推薦
評論