- System Architecture系统架构
- EC功能:EC是notebook笔记本电脑(NB)的组成部分,将传统mainboard(主板MB)的keyboard controller(键盘控制器KBC)延伸扩展,并集成touchpad、keyboard为一体通过KBC控制,使的空间大幅度减小,更加方便用户携带。
- 笔记本电脑拥有别与台式的DC电池供电,因此电池充放以及用电效益就是需要特别考虑的问题,EC配合芯片组在不同工作状态下提供不同的策略以达到省电目的。另外在EC控制充放电以及检测电池状态也可以保护电池,保护电脑运行数据,延长电脑的使用寿命。EC可以控制高度集成的笔记本电脑散热噪音和功效的问题,根据热传感器反馈的CPU和GPU温度智能调节风扇转速。
- 常见的H/W架构:
现在笔记本硬件线路系统中EC架构主要分为两种:
老版本中BIOS会挂载到EC的X-BUS总线上,与EC CODE,keyboard,touchpad设备放在一起,通过LPC BUS总线连接南桥,而新版本回见BIOS挂载在南桥下通过SPI或者LPC总线连接,而EC CODE(EC F/W)则挂载在EC下面。
老版本设计比较简便,并且节省成本,适合早期性能不足的时候使用,而新版本在性能高的情况下不容易抢占总线导致卡死,可以提高性能,提升运行速率。简单来说:老版本成本少,新版本性能高。类似BIOS引导的UEFI和legacy的区别。
- EC与HOST主机通信方式
EC与南桥SB通过LPC总线相连接,因此EC主要通过LPC总线与HOST进行通信,同时EC会将SMI系统管理中断和SCI系统控制中断的引脚拉到南桥上,即EC也可以发送系统终端通知芯片组,芯片组再获取相关的EVENT事件。
- LID
- LID意为盖子,是指笔记本的翻盖合盖过程,即为panel版开关的过程。在大部分笔记本电路上LID是通过翻盖的magnet switch IC磁开关芯片检测LID状态是open还是close H/W的,通常也会作为笔记本屏幕背光板的信号。
- LID OPEN信号与EC的GPIO pin连接,即为LID状态变化会使EC接收中断并发送SCI通知主机自行相应程序,通常第一次开机显示屏是开的,没有供电无法获取LID状态,此时会根据LID状态设定,在系统装载中也会更新LID状态
- LID close与LID open信号基本一致,区别在于状态相反,系统选项也可以自行设置合盖时执行的代码段:do nothing不执行,Standby待机,hibernate休眠.
- Keyboard Introduction键盘介绍
- PC主板中有一颗专用i8042接口芯片处理键盘,集成在sb中,其控制keyboard工作过程,包括加电自检,键盘扫描、与芯片组沟通,而在笔记本中这部分主要由EC负责,EC中集成KBC模块类似于8042,其内置的键盘和触碰面板也是由ec控制,按照ps2协议工作,通过ec发送给主机。
- 键盘按下或者松开时产生扫描码scan code,其分为make code通码 和break code断码。scan code一共有三种代码:set1、set2、set3,ps接口默认set2,ec会将set2转为set1推送给主机。set1中只有一个字节,通断码的区别在最高位为0时为make code,反之则为break code。
A KEY | set1 | set2 | set3 |
make code | 0x1E | 0x1C | 0x1C |
break code | 0x9E | 0xf0,0x1c | 0xf0,0x1c |
- 键盘一般通过行列地址扫描获取其matrix address矩阵地址(物理地址)而后转为matrix value(矩阵值),判断值为功能键还是标准按键,然后转为set2在转为set1发送给主机,主机再发送给相应的driver和API。
矩阵→物理地址→矩阵值→字符set1→字符set2→主机
- hot key热键是通过ec fw进行处理:fn功能键没有scan code 但存在物理地址,因此ec可以通过检测矩阵地址的方式-后置一个或多个flag,再通过flag判断按下值的差异然后发送信号(如FN发送Q_EVENT),这样子主机根据按键来制定各种各样功能
- host2ec io port command命令
- 0x60数据端口,0x64命令端口,EC支持命令如下:
命令 | 注释 |
EDh | 设置LED。Keyboard收到此命令后,一个LED设置会话开始。Keyboard首先回复一个ACK(FAh),然后等待从60h端口写入的LED设置字节,如果等到一个,则再次回复一个ACK,然后根据此字节设置LED。然后接着等待。。。直到等到一个非LED设置字节(高位被设置),此时LED设置会话结束。 |
EEh | 诊断Echo。此命令纯粹为了检测Keyboard是否正常,如果正常,当Keyboard收到此命令后,将会回复一个EEh字节。 |
F0h | 选择Scan code set。Keyboard系统共可能有3个Scan code set。当Keyboard收到此命令后,将回复一个ACK,然后等待一个来自于60h端口的Scan code set代码。系统必须在此命令之后发送给Keyboard一个Scan code set代码。当Keyboard收到此代码后,将再次回复一个ACK,然后将Scan code set设置为收到的Scan code set代码所要求的。 |
F2h | 读取Keyboard ID。由于EC芯片后不仅仅能够接Keyboard。此命令是为了读取后所接的设备ID。设备ID为2个字节,Keyboard ID为83ABh。当键盘收到此命令后,会首先回复一个ACK,然后,将2字节的Keyboard ID一个一个回复回去。 |
F3h | 设置Typematic Rate/Delay。当Keyboard收到此命令后,将回复一个ACK。然后等待来自于60h的设置字节。一旦收到,将回复一个ACK,然后将Keyboard Rate/Delay设置为相应的值。 |
F4h | 清理键盘的Output Buffer。一旦Keyboard收到此命令,将会将Output buffer清空,然后回复一个ACK。然后继续接受Keyboard的击键。 |
F5h | 设置默认状态(w/Disable)。一旦Keyboard收到此命令,将会将Keyboard完全初始化成默认状态。之前所有对它的设置都将失效——Output buffer被清空,Typematic Rate/Delay被设置成默认值。然后回复一个ACK,接着等待下一个命令。需要注意的是,这个命令被执行后,键盘的击键接受是禁止的。如果想让键盘接受击键输入,必须Enable Keyboard。 |
F6h | 设置默认状态。和F5命令唯一不同的是,当此命令被执行之后,键盘的击键接收是允许的。 |
FEh | Resend。如果Keyboard收到此命令,则必须将刚才发送到Output Register中的数据重新发送一遍。当系统检测到一个来自于Keyboard的错误之后,可以使用自命令让Keyboard重新发送刚才发送的字节。 |
FFh | Reset Keyboard。如果Keyboard收到此命令,则首先回复一个ACK,然后启动自身的Reset程序,并进行自身基本正确性检测(BAT-Basic Assurance Test)。等这一切结束之后,将返回给系统一个单字节的结束码(AAh=Success, FCh=Failed),并将键盘的Scan code set设置为2。 |
20h | 准备读取芯片的Command Byte;其行为是将当前Command Byte的内容放置于Output Register中,下一个从60H端口的读操作将会将其读取出来。 |
60h | 准备写入EC芯片的Command Byte;下一个通过60h写入的字节将会被放入Command Byte。 |
A4h | 测试一下键盘密码是否被设置;测试结果放置在Output Register,然后可以通过60h读取出来。测试结果可以有两种值:FAh=密码被设置;F1h=没有密码。 |
A5h | 设置键盘密码。其结果被按照顺序通过60h端口一个一个被放置在Input Register中。密码的最后是一个空字节(内容为0)。 |
A6h | 让密码生效。在发布这个命令之前,必须首先使用A5h命令设置密码。 |
AAh | 自检。诊断结果放置在Output Register中,可以通过60h读取。55h=OK。 |
ADh | 禁止键盘接口。Command Byte的bit-4被设置。当此命令被发布后,Keyboard将被禁止发送数据到Output Register。 |
AEh | 打开键盘接口。Command Byte的bit-4被清除。当此命令被发布后,Keyboard将被允许发送数据到Output Register。 |
C0h | 准备读取Input Port。Input Port的内容被放置于Output Register中,随后可以通过60h端口读取。 |
D0h | 准备读取Outport端口。结果被放在Output Register中,随后通过60h端口读取出来。 |
D1h | 准备写Output端口。随后通过60h端口写入的字节,会被放置在Output Port中。 |
D2h | 准备写数据到Output Register中。随后通过60h写入到Input Register的字节会被放入到Output Register中,此功能被用来模拟来自于Keyboard发送的数据。如果中断被允许,则会触发一个中断。 |
- 命令代码如下:
void host2ec_send_cmd(char cmd)
{
#ifdef asm
__asm
{
in al,64h
test al,2
jz send_cmd
ret
send_cmd: mov bl,0ADh
out 64h,bl
}
#else
static int rxec = (*(base+0x64));
if(rxec & 0x2)
{
host2ec_send_cmd(cmd);
}
else
*(base+0x64)=cmd;
#endif
return P_OK;
}
char ec2host_read_key(char *rx)
{
#ifdef asm
__asm
{
in al,64h
test al,1
jnz read_key
ret
read_cmd: in al,60h
}
#else
static int rxec = (*(base+0x64));
if(rxec & 0x1)
{
*rx= (*(base+0x60));
}
else
ec2host_read_key(rx);
#endif
return *rx;
}
Status Register(状态寄存器)的状态位如下所述:
Bit7: PARITY-EVEN(P_E):从键盘获得的数据奇偶校验错误
Bit6: RCV-TMOUT(R_T): 接收超时,置1) M: c i0 d* p- z& O' i* R2 v6 v
Bit5: TRANS_TMOUT(T_T): 发送超时,置14 Y' s! ]& O. L6 Q K9 P
Bit4: KYBD_INH(K_I): 为1键盘没有被禁止。为0键盘被禁止。! C5 `1 f( M+ @% s1 ~2 O) U5 v
Bit3: CMD_DATA(C_D): 为1输入缓冲器中的内容为命令,0输入缓冲器中的内容为数据。
Bit2: SYS_FLAG(S_F): 系统标志,加电启动置0,自检通过后置1
Bit1: INPUT_BUF_FULL(I_B_F): 输入缓冲器满置1,i8042 取走后置0' q' g/ X4 ~ G' F
BitO: OUT_BUF_FULL(O_B_F): 输出缓冲器满置1,CPU读取后置0