笔记本电脑的内置键盘是不可缺少的输入设备,它经历了二十几年的迭代才形成如今的设计标准(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文章
16977浏览量
350206 -
笔记本电脑
+关注
关注
9文章
1397浏览量
48065 -
键盘
+关注
关注
4文章
858浏览量
39574 -
电脑键盘
+关注
关注
0文章
14浏览量
12274 -
GPIO
+关注
关注
16文章
1196浏览量
51896
发布评论请先 登录
相关推荐
评论