重启,蓝屏,关机,休眠,一系列灾难性的错误均有可能是温度过高引起。即使是行业的领头羊,也经常性地栽倒在这个问题上。虽说这个问题应该是Thermal工程师应该考虑的问题,但作为可以控制风扇和可以通知HOST端的EC工程师来说,也应该了解Thermal的一些细节,以期能够快速准确的想出解问题的思路。
1 CPU温度
想要控制风扇,首先要知道当前温度。一般来说,板子上当属CPU温度最高,但是也有二般的情况,要依据Thermal工程师的实测来决定。EC通常可以获得CPU温度,环境温度和独显温度(PCH和内存也可获取,)。EC要取三者中的温度最高者,作为控制风扇转速的依据。
1.1 SMBUS方式
温度一般都是通过SMBUS获取,读取时要遵守SMBUS规范。业界EC厂商一般都会请软件VENDOR帮他们开发basecode,然后OEM厂商直接使用base code留出的接口来作温度读取的功能。这些接口通常都是使用一个数组来完成。
{0, 0x98, SMB_READ_BYTE, 0x01, (BYTE *)&Therm_Info.TempCPU}
这是数组中的一项,其结构体类型为:
typedef volatile struct _OEMSMB_DESCRIPTOR
{
BYTE Chnl; /* SMBusChannel. */
BYTE ADDR; /* SlaveAddress. */
BYTE PRTCL; /*protocol. */
BYTE DevCmd; /* DeviceCommand. */
BYTE *pntr; /* SMBusBuffer Pointer. */
} OEMSMB_DESCRIPTOR;
从其定义,我们可以看出上述数组中的那个元素,其含义为:要以一个BYTE的方式读取SMBUS0 Channel上,Slave Address为0x98,偏移(Command)为0x01的值,读取成功后,赋值给Therm_Info.TempCPU变量。
这种设计很巧妙:一方面,它将底层的细节封装,大大方便了OEM EC工程师的开发;另一方面,他将程序功能细化,该段代码只读CPU温度,不牵涉风扇控制或其它一些功能。这样如果出错,只需要改动这个数组元素即可。
有很多初学EC的人,都想搞懂ECSMBUS读取设备的整个细节,但往往事与愿违。如果有人对我说,他看懂EC SMBUS代码了,我就会说,我不懂这块,你给我讲讲吧,结果他讲的基本都会错。个人认为,这个SMBUS和PS2功能是整个EC最难懂的地方。我不建议搞懂这块,因为真没啥用,只需要知道接口就可以。更不建议心血来潮换代码的KERNEL,因为自己写的代码没有经过严格的测试,并不健壮。
虽然不需要搞懂整个ECSMBUS代码,但了解一下协议还是有必要的。网上有SMBUS2.0 SPEC,可以查看一下。遇见问题,可以以此为依据进行调试。
1.2 PECI方式
PECI是INTEL发布的继SMBUS过后,又一个可以获取温度的单线制协议,这既可以传输数据,也可以接收数据。PECI真是神一般的东西,让EC可以直接操纵CPU的MSR寄存器。但EC使用最多的还是读CPU温度。
读CPU温度所用CommandFormat为:
将上述第一排Command Format的值写入相应寄存器,然后Check状态寄存器,如果其完成标志位置1,我们就可以通过数据寄存器将byte 5,6读出,然后转换单位后,就成了温度值。
2 降温
2.1 风扇控制
给平台降温,最直接的方式是使用风扇将热量导到机构外部。风扇的速度控制以及转速侦测都交由EC来处理。EC使用PWM(或者DAC)来控制风扇转速。PWM参数有:PWM Frequency,PWM Cycle,PWM Duty Cycle。PWM Frequency要设置得足够高,这样可以保证风扇低速时抖动不厉害,但也不要产生刺耳的叫声,要根据实际情况来调。
EC根据当前CPU温度,设置风扇的占空比,来调节风扇转速。业界一般有两种做法:设置固定占空比和根据转速调节占空比。
2.1.1 设置固定占空比
根据CPU温度范围,设定一定级别,选择恰当的滞回值,给该级别设定固定的CPU占空比。当CPU温度落到该区间内,就将PWM Duty Cycle赋上该级别的值。这样做的缺点是:Thermal工程师设置值时,假定风扇永远是新品,但世界万物都逃不过岁月的侵蚀,风扇也有一天会老去,相应的占空比也不会达到以前的转速。这样散热效果会降低。最好,将最大级别的Duty Cycle设为100%,这样即使有一天风扇老去,潜力仍然要被最大化压榨。
2.1.2 根据转速调节占空比。
在一定的温度范围内,设置一个固定的转速,根据这个转速,设置PWM占空比,让实际转速和设置转速慢慢靠近。这种调节比较精确。但准确就一定是好吗?不一定。为了解决风扇个体间差异以及老化问题,这个固定的转速也需要一定的转速容差。只要在容差范围内,都要做到可以接受。这种设置方法是在一点点地假定(改变一点占空比,读一下转速值),势必造成速度慢,如果升温过快,转速不能立即调上去,为了解决这个问题,只能让其在一个较小的Timer中轮询,这样又会造成资源的大量占有,会影响比Timer优先级小的中断。所以做的时候一定要权衡好速度,资源和容差。
2.2 CPU Throttling
想让CPU温度降低,除了控制风扇转速外,还可以降低CPU频率,或者做Throttling动作。
Throttling可以交给HOST端来做,也可以让EC来做。EC侦测CPU温度过高,就将ProcHot#拉低。CPU开始做Throttling动作,等到其温度回到设定值以下,再将ProcHot#复原。这个动作比较简单粗暴,但是效果很好,可以快速降温。但是如果用户在看高清视频的话,会变得有点卡。