Files
Power-off-analysis/温控与EC传感器分析笔记.md
2026-04-04 15:32:51 +08:00

727 lines
36 KiB
Markdown
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 1. 背景与现象
- **设备**Google KaisaAcer CXI4 Chromebox基于 Puff baseboard
- **固件**coreboot + Chrome EC
- **主要问题**
- Windows 下曾出现热事件关机;
- EC 控扇仅依赖一颗板载热敏电阻,温度响应滞后于 CPU风扇启动与拉满偏晚。
本文整理 Puff/Kaisa 上 **温度传感器、EC 温控、DPTF 控扇** 的整体路径,并记录调试 DPTF FAND/\_FSL 时的关键发现。
---
## 2. 温度与 EC 的关系概览
- **CPU/主机侧温度**
- Linux`/sys/class/thermal/thermal_zone*` 中的 `TCPU``x86_pkg_temp` 等,由 CPU/PCH 提供,不经过 EC。
- WindowsDPTF 通过 ACPI 热区(如 `\_SB.PCI0.TCPU`)取 CPU 温度。
- **EC 侧温度**Puff/Kaisa
- 只有 **1 路板载 thermistor**
- ADC`ADC_TEMP_SENSOR_1`NPCX_ADC_CH0
- 逻辑 ID`TEMP_SENSOR_CORE`
- 读函数:`get_temp_3v3_30k9_47k_4050b`
- EC 每秒读这路 ADC写入 EC memory map对外通过 ACPI 暴露为 `TSR0`
**结论**
目前板上可用的温感来源只有两类CPU 自身温度 + EC 的一颗板载 thermistor没有额外硬件温感。
---
## 3. EC 控扇链路Puff/Kaisa
### 3.1 板级配置(`ec/board/puff/board.c` & `board.h`
- 温度枚举:
```c
enum temp_sensor_id {
TEMP_SENSOR_CORE,
TEMP_SENSOR_COUNT
};
```
- ADC 与 `temp_sensors[]`
```c
[ADC_TEMP_SENSOR_1] = {
.name = "TEMP_SENSOR_1",
.input_ch = NPCX_ADC_CH0,
.factor_mul = ADC_MAX_VOLT,
.factor_div = ADC_READ_MAX + 1,
},
const struct temp_sensor_t temp_sensors[] = {
[TEMP_SENSOR_CORE] = {
.name = "Core",
.type = TEMP_SENSOR_TYPE_BOARD,
.read = get_temp_3v3_30k9_47k_4050b,
.idx = ADC_TEMP_SENSOR_1,
},
};
```
- EC 的温阈值与风扇曲线(`thermal_params[]`
```c
const static struct ec_thermal_config thermal_a = {
.temp_host = {
[EC_TEMP_THRESH_WARN] = 0,
[EC_TEMP_THRESH_HIGH] = C_TO_K(68),
[EC_TEMP_THRESH_HALT] = C_TO_K(78),
},
.temp_host_release = {
[EC_TEMP_THRESH_WARN] = 0,
[EC_TEMP_THRESH_HIGH] = C_TO_K(58),
[EC_TEMP_THRESH_HALT] = 0,
},
.temp_fan_off = C_TO_K(40), // <40℃ 关风扇
.temp_fan_max = C_TO_K(60), // ≥60℃ 满速
};
struct ec_thermal_config thermal_params[] = {
[TEMP_SENSOR_CORE] = thermal_a,
};
```
### 3.2 通用 thermal 引擎(`ec/common/thermal.c`
- 每秒执行一次 `thermal_control()`
1. 遍历所有温度传感器(这里只读 `TEMP_SENSOR_CORE`
```c
for (i = 0; i < TEMP_SENSOR_COUNT; ++i)
rv = temp_sensor_read(i, &t);
```
2. 根据 `thermal_params[i].temp_host[]` 与 `temp_host_release[]` 统计 WARN/HIGH/HALT触发
- `chipset_force_shutdown(CHIPSET_SHUTDOWN_THERMAL);`
- `throttle_ap(THROTTLE_ON, THROTTLE_HARD/SOFT, THROTTLE_SRC_THERMAL);`
3. 根据 `temp_fan_off` 和 `temp_fan_max` 计算该传感器需要的风扇百分比:
```c
f = thermal_fan_percent(thermal_params[i].temp_fan_off,
thermal_params[i].temp_fan_max,
t);
fmax = max(fmax, f);
```
4. 对所有风扇设置统一需求:
```c
for (i = 0; i < fan_get_count(); i++)
fan_set_percent_needed(i, fmax);
```
**结论**
在 “EC 自动控扇” 模式下,风扇完全由 EC 根据这路 thermistor + `thermal_a` 曲线驱动。
---
## 4. DPTF 与 EC 的桥接ACPI/DPTF 侧)
### 4.1 温度TSR0..TSR4
- coreboot 的 `ec_dptf_helpers.c` 为 DPTF temp participants 生成 `_TMP`
```c
/* TSRx._TMP = EC0.TSRD(x) */
acpigen_write_method_serialized("_TMP", 0);
acpigen_emit_byte(RETURN_OP);
acpigen_emit_namestring(acpi_device_path_join(ec, "TSRD"));
acpigen_write_integer(tsr_index); // 0..4
```
- `ec.asl` 中:
```asl
Method (TINS, 1, Serialized)
{
Switch (ToInteger (Arg0)) {
Case (0) { Return (TIN0) }
Case (1) { Return (TIN1) }
...
Default { Return (TIN0) }
}
}
Method (TSRD, 1, Serialized)
{
Local0 = \_SB.PCI0.LPCB.EC0.TINS (Arg0)
/* 检查 TNCA/TNPR/TNOP/TBAD 省略 */
Local0 += \_SB.PCI0.LPCB.EC0.TOFS
Local0 *= 10 // 转为 1/10 K
Return (Local0)
}
```
- Puff 上:只有 `TEMP_SENSOR_CORE` → `TIN0` → `TSR0`,其它 TSR1..TSR4 基本为空。
### 4.2 风扇TFN1 + FST/FSL + FAND
根据 DPTF 规范FAN participant`TFN1`)需要提供:
- `_FST`:返回 `{ Revision, Control, Speed }`
- `_FSL(level)`:设置 fan level/duty。
Chrome EC 路径(`ec_dptf_helpers.c`
- 写回包 `TFST`
```c
/* TFST = { Revision, Control, Speed } */
acpigen_write_name("TFST");
acpigen_write_package(3);
acpigen_write_integer(0); /* Revision */
acpigen_write_integer(0); /* Control */
acpigen_write_integer(0); /* Speed */
acpigen_pop_len(); /* Package */
```
- `_FST` 实现大致为:
```c
/* _FST: TFST[1] = EC0.FAND; TFST[2] = FANx_RPM; return TFST */
acpigen_write_method_serialized("_FST", 0);
acpigen_write_store();
acpigen_emit_namestring(acpi_device_path_join(ec, "FAND"));
acpigen_emit_byte(INDEX_OP);
acpigen_emit_namestring("TFST");
acpigen_write_integer(1); // Control
...
acpigen_write_store();
acpigen_emit_namestring(acpi_device_path_join(ec, "FAN0")); // 实际 RPM 来源
acpigen_emit_byte(INDEX_OP);
acpigen_emit_namestring("TFST");
acpigen_write_integer(2); // Speed
...
acpigen_emit_byte(RETURN_OP);
acpigen_emit_namestring("TFST");
acpigen_pop_len();
```
- `_FSL(level)` 实现:
```c
/* _FSL(Arg0): Store(Arg0, EC0.FAND) */
acpigen_write_method_serialized("_FSL", 1);
acpigen_write_store();
acpigen_emit_byte(ARG0_OP);
acpigen_emit_namestring(acpi_device_path_join(ec, "FAND"));
acpigen_pop_len();
```
其中 `FAND` 对应 EC ACPI RAM 中地址 `0x04``EC_ACPI_MEM_FAN_DUTY`),在 `ec_commands.h` 定义为:
```c
/* DPTF Target Fan Duty (0-100, 0xff for auto/none) */
#define EC_ACPI_MEM_FAN_DUTY 0x04
```
ACPI 通过 `EC_ACPI_MEM_FAN_DUTY` 写入后EC C 侧(`ec/common/acpi.c`)处理:
```c
case EC_ACPI_MEM_FAN_DUTY:
dptf_set_fan_duty_target(data);
break;
```
`dptf_set_fan_duty_target()` 实现(`ec/common/fan.c`
```c
/* 0-100% sets duty, out of range means let the EC drive */
void dptf_set_fan_duty_target(int pct)
{
int fan;
if (pct < 0 || pct > 100) {
/* 超出范围:交回 EC 自动控扇 */
for (fan = 0; fan < fan_count; fan++)
set_thermal_control_enabled(fan, 1);
} else {
/* 合法 0-100按 duty 控扇,关闭 thermal 自动控扇 */
for (fan = 0; fan < fan_count; fan++)
set_duty_cycle(fan, pct);
}
}
```
读取时,若处于 duty 模式,`dptf_get_fan_duty_target()` 返回 0100否则返回 -1对应 FAND=0xff。
**结论(非常重要)**
- 写入 **0100**DPTF 接管风扇EC 用该 duty 控扇thermal 自动模式被关闭;
- 写入 **0xff 或越界值(<0 或 >100例如 0x80**:退回 EC 自动控扇模式FAND 对外显示为 0xff。
---
## 5. 模式选择EC 控扇 vs Windows DPTF 控扇
### 5.1 EC 控扇模式(稳定默认)
coreboot defconfig 中:
```text
CONFIG_MINIPC_EC_FULL_FAN_CONTROL=y
CONFIG_DRIVERS_INTEL_DPTF_DISABLE_ACTIVE_FAN=y
```
- DPTF 风扇参与者被隐藏/禁用 Active Policy
- EC 在 `_REG` 时写 `FAND=0xFF`,明确进入自动模式;
- 风扇完全由 EC thermal 引擎(第 3 节)驱动。
适用:
- 无 Windows DPTF 驱动或不希望依赖 DPTF
- 简化行为,只调一条 EC 曲线。
### 5.2 Windows DPTF 控扇模式(实验/优化)
coreboot defconfig 中:
```text
# CONFIG_MINIPC_EC_FULL_FAN_CONTROL is not set
# CONFIG_DRIVERS_INTEL_DPTF_DISABLE_ACTIVE_FAN is not set
CONFIG_DRIVERS_INTEL_DPTF_ECTST_FAND_DEBUG=y
```
- DPTF FANTFN1暴露给 Windows
- Active Policy 启用DPTF 根据 CPU 温度 + TSR0 等决定何时 `_FSL(level)`
- EC 通过 `dptf_set_fan_duty_target(level)` 接收 duty
- 0100DPTF 覆盖;
- 0xff/越界:交回 EC 自动。
**前提**
Windows 中必须安装并启用 Intel DPTF 驱动INT3400/INT3404 等设备正常工作),否则不会按策略调用 `_FSL()`。
---
## 6. ECT0 调试:为什么 `_FSL(0x80)` 后 FAND 一直是 0xff
在 Windows 下,使用 `ECT0._FST/_FSL` 调试 FAND`logs.txt`
```powershell
[1] Current FAND from _FST:
FAND = 0x46 # 70%,说明曾经处于 duty 模式
[2] Writing FAND via _FSL(0x80) ...
[3] Read-back FAND after _FSL:
FAND = 0xff
[4] 继续监视 _FST:
FAND 始终是 0xff
```
**结合第 4 节的实现:**
- 0x80 = 128 > 100 → 按 `dptf_set_fan_duty_target()` 的语义,这是“越界值”:
- 进入 `pct < 0 || pct > 100` 分支;
- 调用 `set_thermal_control_enabled(fan, 1)`**恢复 EC 自动控扇**
- `dptf_get_fan_duty_target()` 返回 -1对 ACPI 显示为 FAND=0xff。
**正确结论**
- **FSL/FST → EC 的链路是通的**,只是你写入的是一个“退回自动”的值(>100EC 正确地退出了 DPTF duty 模式;
- `_FST` 一直看到 FAND=0xff说明当前处于 “auto/none” 状态,而不是链路失效。
**正确的测试方式**
- 要验证 DPTF/ECT0 控扇是否生效,应使用 **0100** 的值:
```powershell
ectest -acpi \_SB.ECT0._FSL 50 # 50%
ectest -acpi \_SB.ECT0._FST # FAND 应为 0x32且风扇转速有变化
```
- 要主动退回 EC 自动控扇,可以写 **0xff 或 >100**(例如 0x80
### 13.7 用其他方法监控 DPTF 是否发送风扇控制信号
除轮询 `\_SB.ECT0._FST` 看 FAND 是否随温度变化外,可用脚本 `Monitor_DPTF_Fan.ps1` 做两类监控需管理员、ectest 可用):
| 模式 | 说明 |
|------|------|
| **check** | 检查本机是否有 DPTF/ESIF 服务、ACPI 设备 INT3404/INT3400、相关驱动判断 DPTF 栈是否加载。 |
| **poll** | 高频率轮询 `_FST`(默认每 200ms将时间戳与 FAND 写入 CSV持续一段时间默认 60s。对 CPU 加压时若 CSV 中 FAND 始终不变,可判断 DPTF 未通过 _FSL 写 FAND。 |
| **watch** | 专用于**监控 INT3404 是否发送控扇信号**:轮询 `_FST`,仅在 FAND **发生变化**时在控制台打印(并写 CSV。若加压过程中出现 “FAND changed: 0xff -> 0x50” 等,说明有对象(多为 INT3404/DPTF写入了 _FSL若始终无输出则 INT3404 未写 _FSL 或 EC 覆盖了写入。 |
| **etw** | 用 logman 采集 DPTF/ESIF 的 ETWEsifLfEtwProvider 等),记录一段时间后 tracerpt 转 CSV。若已装 Intel DPTF 驱动,可查看是否有风扇/ACPI 相关事件。 |
| **all** | 先 check再运行 etw按提示加压后回车停止最后做 poll 并落盘。 |
用法示例:
```powershell
.\Monitor_DPTF_Fan.ps1 -Mode check
.\Monitor_DPTF_Fan.ps1 -Mode watch -PollSeconds 120 -PollIntervalMs 150 # 监控 INT3404 是否发控扇
.\Monitor_DPTF_Fan.ps1 -Mode poll -PollSeconds 120 -PollIntervalMs 150
.\Monitor_DPTF_Fan.ps1 -Mode etw
.\Monitor_DPTF_Fan.ps1 -Mode all
```
结论解读:若 **poll** 阶段在负载下 FAND 始终不变,且 **check** 未见 DPTF 设备/服务,则当前系统未通过 DPTF 发送风扇控制信号;若 ETW 中有相关事件,可进一步对照 DPTF 文档看是否包含 _FSL 调用。
- 要主动退回 EC 自动控扇,可以写 **0xff 或 >100**(例如 0x80
```powershell
ectest -acpi \_SB.ECT0._FSL 0xff # 或 0x80 等 >100
ectest -acpi \_SB.ECT0._FST # FAND 应回到 0xff
```
---
## 7. 总结
1. Puff/Kaisa 的 EC 只有一颗板载 thermistor`TEMP_SENSOR_CORE`),所有 EC 自动温控与关机/限频都基于这一路。
2. coreboot + Chrome EC 已经在 ACPI/DPTF 层实现了完整的 FAN 接口TFN1._FST/_FSL
- `_FSL(level)` → 写入 `EC_ACPI_MEM_FAN_DUTY` → `dptf_set_fan_duty_target(level)`
- `_FST()` → 回读当前 FAND 与实际 RPM。
3. EC 明确定义了 fan duty 的语义:
- **0100**DPTF 直接指定 dutyEC 关闭 thermal 自动控扇;
- **0xff 或越界**:退出 DPTF duty 模式,交回 EC 自动控扇FAND 显示为 0xff。
4. Windows 下已枚举到 INT3400/INT3404在设备管理器中分别显示为 **Intel(R) Dynamic Tuning Manager**INT3400与 **Intel(R) Dynamic Tuning Fan Participant**INT3404设备实例路径为 `ACPI\INT3400\0`、`ACPI\INT3404\0`,说明 **DPTF 风扇控制器栈与 ACPI 风扇设备都是存在的**。
5. 实测轮询 `\_SB.ECT0._FST` 时FAND 只在手动 `_FSL(x)` 时改变,负载/温度变化本身并不会让 DPTF 自动写入 FAND结合 INT3404 存在但 FAND 不随温度变化,可以判断:当前固件/策略仍以 **EC 自动曲线为主控DPTF 风扇参与者更多处于观察/可选控制状态**。
6. “`_FSL(0x80)` 后 FAND 一直 0xff” 是因为 0x80>100被 EC 解读为 “放弃 DPTF 覆盖、恢复 EC 自动”,而非链路未接通。
7. 选择 EC 控扇还是 DPTF 控扇,只需在 coreboot defconfig 中切换:
- EC 控扇:`CONFIG_MINIPC_EC_FULL_FAN_CONTROL=y` + `CONFIG_DRIVERS_INTEL_DPTF_DISABLE_ACTIVE_FAN=y`
- DPTF 控扇:两者都不设,并确保 Windows 中 DPTF 驱动工作正常。
### 7.1 固件 20260224034907 配置确认DPTF 控扇固件)
- **固件**`20260224034907` 目录下为 `coreboot_edk2-kaisa-mrchromebox_20260224.rom` 的构建产物,含 `.config`、`build.log`。
- **.config 中与风扇控制相关的项**
- `# CONFIG_MINIPC_EC_FULL_FAN_CONTROL is not set` → EC **非**全权控扇,主机可写 FAND
- `# CONFIG_DRIVERS_INTEL_DPTF_DISABLE_ACTIVE_FAN is not set` → DPTF 主动风扇策略**开启**
- `CONFIG_DRIVERS_INTEL_DPTF_ECTST_FAND_DEBUG=y` → 暴露 ECT0 调试设备,可读/写 FAND。
- **结论**:该固件为 **DPTF 控扇** 配置,风扇应由 DPTF 通过 _FSL 写 FANDEC 按 FAND 执行。
- **与实测的差异**:在 Windows 下用 `Monitor_DPTF_Fan.ps1 -Mode watch` 观察CPU 升温时 **FAND 从未变化**(无 “FAND changed”说明 **DPTF 驱动/策略没有在按温度调用 _FSL**。问题在 **Windows/DPTF 侧**,不在固件是否为 DPTF 控扇。
- **建议**:在 Windows 中检查电源/热管理是否有 “Intel DPTF” 或 “平台热管理” 并确认已启用;从 Microsoft Update Catalog 或 OEM 安装/更新 “Intel Dynamic Platform and Thermal Framework” 驱动后,再以 watch 模式观察负载下 FAND 是否变化。
### 7.2 Windows 电源/热管理检查步骤(驱动已确认时)
硬件与 DPTF 驱动INT3400/INT3404、esifsvc已确认正常时若 FAND 仍不随温度变化,可逐项检查电源与热管理是否“关掉”了 DPTF 控扇:
| 步骤 | 位置 | 检查内容 |
|------|------|----------|
| 1 | **设置 → 系统 → 电源** | 查看当前“电源模式”(平衡/最佳性能等部分机型在此有“热管理”或“Intel 图形/平台”相关项,确认未选“静音/省电”导致不拉高风扇。 |
| 2 | **控制面板 → 电源选项 → 更改计划设置 → 更改高级电源设置** | 在列表中查找 **处理器电源管理**、**Intel**、**Thermal**、**平台热管理** 或 OEM如 Acer提供的“风扇/热管理”子项。若有“最大处理器状态”“散热方式”等,可先选“主动/积极散热”或提高最大状态,排除因电源计划限制导致 DPTF 不写 _FSL。 |
| 3 | **设备管理器 → 系统设备 → Intel(R) Dynamic Tuning Fan Participant** | 属性 → 驱动程序:确认设备已启用、无感叹号;若有“电源管理”选项卡,可取消勾选“允许计算机关闭此设备以节约电源”(若存在),避免被省电关闭。 |
| 4 | **OEM 自带软件** | 若装有 Acer Care、Lenovo Vantage、Dell Power Manager 等,在“性能/散热/风扇”类设置中查看是否有“静音模式”“禁用 DPTF”“自定义风扇曲线”等若有且设为静音或禁用 DPTF改为平衡/性能或启用 DPTF 后再用 watch 观察。 |
| 5 | **当前电源方案** | 管理员 PowerShell`powercfg /getactivescheme` 查看当前方案;必要时切换为“高性能”或“卓越性能”后再次运行 `Monitor_DPTF_Fan.ps1 -Mode watch`,看负载下是否出现 “FAND changed”。 |
脚本 `Monitor_DPTF_Fan.ps1 -Mode check` 会输出当前电源方案及上述 14 的手动检查提示,便于逐项核对。
这份笔记即为当前 Puff/Kaisa 上温控与 EC/DPTF 行为的整理,可作为后续调整 EC 曲线或 DPTF 策略时的参考。
# 温控与 EC 传感器分析笔记
本文档记录 Chromebox 刷 coreboot 后Windows 热关机、Linux 温控、EC 温度源及 I2C 设备识别相关的有用信息。
---
## 1. 问题背景
- **现象**Windows 下出现热事件关机EC 控扇仅依赖板载温度传感器,延迟与偏差大,导致风扇响应滞后。
- **根因**EC 只有一路 ADC 热敏电阻“Core”且该点滞后于 CPU 实际温度Windows 负载/功耗较高时易触发过热关机。
---
## 2. 热区与 EC 的关系Linux 视角)
- **thermal_zone**(如 TCPU、x86_pkg_temp内核/CPU 热区,数据不经过 EC。
- **EC 获取 CPU trip 的方式**
- **硬件**THERMTRIP#、PROCHOT# 等引脚由 CPU 拉低EC 直接检测。
- **软件**ACPI Notifythermal zone critical 等)可通知 EC。
- **直接连到 EC 的温度**cros_ec 上报的 “Core” = EC 自己读的 ADC 热敏电阻INT3400 与 EC 策略/关机链路相关。
---
## 3. Linux 温控 vs Windows DPTF
| 项目 | Linux 温控 | Windows DPTF |
|------------|--------------------------|---------------------------------|
| 策略 | 内核 governor / thermald | OEM 策略引擎 + ACPI |
| 应用感知 | 一般无 | 有(游戏/办公等不同策略) |
| 风扇 | 内核 cooling 或 fancontrol | 常由 EC 独管DPTF 不控扇 |
DPTF 未真正控扇常见原因:风扇权在 EC或 OEM 未把风扇暴露给 DPTF或 Windows 无 EC 风扇驱动。
---
## 4. EC 温度源(以 Puff 板为例)
- **当前**:仅 **1 路** 温度 —— ADC 热敏电阻(`ADC_TEMP_SENSOR_1` → `TEMP_SENSOR_CORE`),读函数 `get_temp_3v3_30k9_47k_4050b`。
- **无 I2C 温度传感器**board.c 里 temp_sensors[] 只有上述 ADC 项EC 的 I2C 上接的是 INA3221、PPC、TCPC、POWER、EEPROM 等,无温感芯片。
- **增加温度源的可能**:若硬件有预留(空余 ADC 通道或 EC I2C 上接温感),可在 EC 源码里加 temp_sensor 配置;否则需改硬件。
---
## 5. 主机 I2C 与 EC I2C 是两套总线
- **主机侧**`i2cdetect -l` 的 i2c-0i2c-11CPU/PCH 的 SMBus、i915 等,由 Linux 枚举;扫描用 `i2c_scan.sh`(调用 i2cdetect
- **EC 侧**EC 固件里 `i2c_ports[]` 定义的 GPIO_I2C0I2C7设备在 board.c 中定义。
- **结论**:主机 I2C 扫描到的地址(如 0x08、0x44、0x52…**不会**出现在 EC 的 board.c 里EC 能扫的只是自己那几条总线。
---
## 6. 本机 EC I2C 扫描结果ectool-cec i2cxfer
| EC Port | 扫到地址 | 用途/推断 |
|---------|--------------|-----------|
| 1 | 0x40 | 电流/功率类,非标准 INA3221 |
| 3 | 0x2c 0x38 0x39 0x3d 0x3f 0x42 | 见下表 |
| 5 | 0x20 | EEPROM (24cxx) |
### Port 3 各地址识别摘要
| Addr | reg 0x00 / 0x80 等 | 可能型号/类型 |
|------|--------------------|----------------|
| 0x2c | 0x77 0x79…index/data 访问 | Nuvoton Super I/O / I2C 多功能(如 NCT5532D、NCT5577D、NCT38xx**可能带温度,需 index/data 读** |
| 0x38 | 0x30 0x30 (ASCII) 等 | GPIO/IO 扩展或显示 |
| 0x39 | 全 0 | 未初始化或空 |
| 0x3d | 全 0 | 可能 SSD1306 或未初始化 |
| 0x3f | 0x80 = 0x5A 0x5E | 某 PMIC/传感器厂商 Device ID**可能带温度,需查 datasheet** |
| 0x42 | 全 0 | 可能 INA3221 未使能或它用 |
---
## 7. 常见芯片 ID 参考(用于 ec_i2c_identify
- **0x80 = 0x54 0x49**TI INA3221/INA219电流/功率)。
- **0x80 = 0x5A 0x5E**:某厂商 Device ID多见于 PMIC/传感器,具体型号需查该厂商手册。
- **0x2c 总线、首字节 0x77 等**Nuvoton NCT55xx/NCT5577D/NCT38xx 等;访问多为 index/data直接读“reg 0”未必对应真实寄存器。
- **0x20 + 数据区大段 0xff**:常见 EEPROM (24c02 等)。
- **0x38 读得 0x30 0x30**:常见 GPIO/IO 扩展(如 PCA9555
- **0x3c/0x3d 全 0**:常见 SSD1306 等 OLED 未初始化。
---
## 8. 哪个可能是我们要找的温度传感器?
- **首选候选Port 3, 0x2c**
Nuvoton NCT 系常带硬件监控温度;需在 EC 内按 **index/data** 协议和该芯片 datasheet 的温度寄存器 index 读取。
- **次选候选Port 3, 0x3f (0x5A5E)**
可能是带温度通道的 PMIC/传感器;需找到对应 datasheet 确认是否有温度寄存器及地址/格式。
- **其余**0x40/0x42 INA 类、0x38 GPIO、0x39/0x3d、0x20 EEPROM**不视为温度传感器**。
---
## 9. 脚本与工具
| 脚本/命令 | 作用 |
|-----------|------|
| `linux_collect_sensors.sh` | 收集 Linux 下 thermal zone、hwmon、lm-sensors、ectool temps、dmesg、CPU 信息;报告存当前目录或 /tmp。 |
| `i2c_scan.sh` | 主机侧 I2C 扫描i2cdetect扫 i2c-0i2c-N。 |
| `ec_i2c_scan.sh` | EC 侧 I2C 扫描,用 ectool-cec 的 i2cxfer 对指定 port 扫 0x080x77。**须用 ectool-cec**,系统 ectool 无 i2cxfer。 |
| `ec_i2c_identify.sh` | 对指定 port:addr 读 reg 0x00/0x80/0xFE/0xFF/0x0F并给出可能型号推断。 |
### 使用注意
- 脚本行尾须为 **LF**;若出现 `$'\r': 未找到命令` 等,执行:`sed -i 's/\r$//' 脚本名.sh`。
- EC 扫描/识别需 **sudo**,且 **ECTOOL** 指向 ectool-cec例如
`ECTOOL=/home/jack/bin/ectool-cec sudo ./ec_i2c_scan.sh`
---
## 10. 后续可做
- 在 EC 源码中查 0x2c 对应芯片的 datasheet用 **index/data** 读温度寄存器,并在 temp_sensor/thermal 里增加一路。
- 若有 0x5A5E 对应型号的 datasheet确认是否带温度通道及寄存器再在 EC 中实现读取。
- Windows 侧可先通过限 CPU 功耗/电源计划降低热负载,减轻 EC 单路温控滞后带来的热关机。
---
## 11. Puff/Kaisa 上增加一路温度传感器的可行性
### 11.1 地址与硬件对应关系Puff
- **I2C Port 3TCPC0上的 0x2c**:在 Puff 板为 **AN7447 TCPC**`AN7447_TCPC0_I2C_ADDR_FLAGS = 0x2C`),不是独立温感芯片,不能当第二路温度源使用。
- **0x3f**:同颗 AN7447 的 SPI 转 I2C 接口(`AN7447_SPI0_I2C_ADDR_FLAGS = 0x3F`),读到的 0x5A5E 等为 AN7447 相关,**不是**独立 I2C 温度传感器。
- **结论**:当前 Puff 板 EC 可见的 I2C 总线上,**没有空闲的、可用的 I2C 温度传感器芯片**笔记中“Port 3 的 0x2c/0x3f 可能是温感”的推断在本板不成立。
### 11.2 可行方向
| 方向 | 说明 |
|------|------|
| **A. 第二路 ADC 热敏电阻** | 若原理图有未用的 ADC 通道 + 热敏电阻,在 `board.h` 增加 `ADC_TEMP_SENSOR_2` 与对应 `enum`,在 `board.c` 的 `adc_channels[]`、`temp_sensors[]`、`thermal_params[]` 各加一项,并用现有 `get_temp_3v3_30k9_47k_4050b` 或对应 thermistor 读函数。 |
| **B. 新增 I2C 温感芯片** | 若硬件在某一 I2C 总线上**新接**温感(如 TMP112/TMP432 等),需:该总线在 `i2c_ports[]` 中、地址不与现有设备冲突;在 EC 中启用对应 driver如 `CONFIG_TEMP_SENSOR_TMP112`)、在 `board.h` 增加 `TEMP_SENSOR_xxx` 与 `TEMP_SENSOR_COUNT`,在 `board.c` 中增加 `temp_sensors[]` 与 `thermal_params[]`。 |
| **C. 确认 0x5A5E 芯片** | 若某板型在其它 I2C 端口上有独立 0x5A5E 芯片且 datasheet 标明带温度寄存器,可为该芯片写专用 driverindex/data 或普通 I2C 读),再按 B 的方式挂到 `temp_sensors[]`。 |
### 11.3 EC 侧增加一路温度传感器的实现步骤(通用)
1. **board.h**
- 增加 `enum adc_channel` 或 I2C 温感用的 `enum`(若用现有 driver通常只需 `temp_sensor_id`)。
- 在 `enum temp_sensor_id` 中增加新 ID如 `TEMP_SENSOR_BOARD2`),并保证 `TEMP_SENSOR_COUNT` 正确。
2. **board.c**
- **ADC 热敏电阻**:在 `adc_channels[]` 增加一路 ADC在 `temp_sensors[]` 增加一项(`name`、`type`、`read`、`idx`);在 `thermal_params[]` 增加对应 `ec_thermal_config`。
- **I2C 温感**:若为现有 driver如 TMP112在 `temp_sensors[]` 增加一项,`read` 指向 driver 的 `get_val``idx` 为 channel/index同样在 `thermal_params[]` 增加一项。
- 若需参与控扇:在 `setup_thermal()` 等逻辑中为新 sensor 选择/绑定 thermal table。
3. **Kconfig / 构建**
- 若用 I2C 温感 driver在对应 board 的 `Kconfig` 或 `board.h` 中启用 `CONFIG_TEMP_SENSOR_xxx` 及该 driver 所需的 `I2C_PORT_xxx`。
4. **thermal 策略**
- 若希望新传感器参与风扇控制,需在 thermal 逻辑中把新 sensor 的读数纳入(例如与现有 `TEMP_SENSOR_CORE` 取 max或单独阈值并保证 `thermal_params[新ID]` 的 `temp_fan_off` / `temp_fan_max` 等已配置。
### 11.4 小结
- **不改硬件**Puff 上仅能依赖现有 1 路 ADC 热敏电阻Core无法在现有 I2C 设备0x2c/0x3f 均为 AN7447上“多出一路”温度传感器。
- **改硬件**:增加第二路 ADC 热敏电阻,或新接 I2C 温感芯片并接在已有或新增 I2C 总线上,再按 11.3 在 EC 中增加一项 temp_sensor 与 thermal 配置即可。
---
## 12. DPTF 控制风扇的可行性Puff/Kaisa
### 12.1 固件侧已支持 DPTF 控扇
- Puff 的 **DPTF 设计本来就是“DPTF 控扇”**
- `baseboard/acpi/dptf.asl` 中定义了 `DPTF_ENABLE_FAN_CONTROL`、DFPSFan Performance States、DART风扇对 CPU/TSR 的影响)。
- Kaisa 的 `overridetree.cb` 里配置了 **Active Policy**`policies.active[0]` = DPTF_CPU`policies.active[1]` = DPTF_TEMP_SENSOR_0即 **CPU 温度 + 板载温感EC 上报)共同驱动风扇**;另有 `controls.fan_perf[]`、`fine_grained_control`、`step_size` 等。
- 注释写明:"Active Policy: CPU drives fan (DPTF controls via FAND)"。
- 风扇档位由 DPTF 通过 ACPI 写 **FAND** 下发给 ECEC 按 FAND 驱动 PWM固件表和 devicetree 已具备完整策略,**从固件角度看 DPTF 控扇是可行的**。
### 12.2 当前 Kaisa 配置为何是 EC 控扇
- 为规避“Windows 下无人写 FAND、风扇卡在固定转速”的问题当前 defconfig 改为 **EC 完全控扇**
- `CONFIG_MINIPC_EC_FULL_FAN_CONTROL=y`:隐藏 DPTF 风扇设备EC 在 _REG 时写 FAND=0xFFEC 自动控扇)。
- `CONFIG_DRIVERS_INTEL_DPTF_DISABLE_ACTIVE_FAN=y`:关闭 DPTF Active PolicyDPTF 不再写 FAND。
- 这样 Windows 即使没有 DPTF 驱动EC 也会按自身 thermistor 控扇,避免“既不用 DPTF 也不写 0xFF”导致的卡死。
### 12.3 若改为 DPTF 控扇
| 项目 | 说明 |
|------|------|
| **固件配置** | 取消 EC 全权控扇、恢复 DPTF 控扇:`CONFIG_MINIPC_EC_FULL_FAN_CONTROL=n`(或不设),`CONFIG_DRIVERS_INTEL_DPTF_DISABLE_ACTIVE_FAN=n`。重新编译刷写后DPTF 风扇设备可见Active Policy 生效。 |
| **温度源** | DPTF 使用 **CPU 温度**\_SB.PCI0.TCPU+ **EC 上报的板载温感**TSR0 = TEMP_SENSOR_0即 Core。CPU 温度由 OS/驱动提供,响应比单路 EC thermistor 快,有利于提前拉高转速。 |
| **Windows 依赖** | **必须安装 Intel DPTF 相关驱动**(如 INT3400、INT3404 等),否则 OS 不会根据 DPTF 表写 FAND风扇仍可能不随负载变化。驱动可从 Microsoft Update Catalog 或 OEM 包获取。 |
| **Linux** | 若使用内核 thermal + DPTF ACPI需相应驱动/用户态配合写 cooling_device常见做法仍是 EC 控扇或 fancontrol。 |
### 12.4 小结
- **DPTF 控扇在 Puff/Kaisa 上固件可行**:表与策略已就绪,只需改 defconfig 并确保 Windows 有 DPTF 驱动。
- **EC 控扇**:不依赖 Windows 驱动,适合“通用 Windows/无 DPTF”场景但仅有一路板载温感响应偏慢。
- **二选一**:要么 EC 全权控扇(当前配置),要么 DPTF 控扇(改配置 + 装 Windows DPTF 驱动不可同时“DPTF 可见但不写 FAND、EC 也不写 0xFF”否则会再现风扇卡死。
---
## 13. 监视 FAND 与“DPTF 未改变 FAND”的排查
### 13.1 概念DPTF 如何写风扇
- DPTF 控扇时OS 驱动调用 ACPI 方法 **\_FSL**Fine-grained Set LevelACPI 里把参数写入 EC 的 **FAND** 字段EC 固件读 FAND 驱动 PWM。
- **FAND**EC ACPI 中 8 位字段Fan Duty在 `ec.asl` 的 ERAM 里0xFF 表示 EC 自动控扇。
- **\_FSL(Arg0)**DPTF 风扇设备(如 TFN1上的方法实现为 `Store(Arg0, EC0.FAND)`。
- 无法直接“hook \_FSL”监视 \_FSL 的效果 = **轮询读取 FAND**,看其是否随负载/温度变化。
### 13.2 如何监视 FAND
- 固件开启 **CONFIG_DRIVERS_INTEL_DPTF_ECTST_FAND_DEBUG=y** 时,会暴露调试设备 `\_SB.ECT0`
- `\_SB.ECT0._FST()`:读当前 FAND与 TFN1._FST 一致);
- `\_SB.ECT0._FSL(x)`:写 FAND与 DPTF 写路径一致)。
- **Windows**:安装 ec-test-appOpenDevicePartnership ectest在管理员 PowerShell 中轮询:
```powershell
while ($true) {
ectest -acpi \_SB.ECT0._FST
Start-Sleep -Seconds 1
}
```
- **Linux**:若 ectool 支持读 FAND 或 EC RAM 中对应偏移,可写脚本轮询;或通过 cros_ec 接口读 thermal/风扇相关节点(视内核暴露而定)。
### 13.3 “监视过 FAND但 DPTF 似乎没有改变 FAND”的排查
| 检查项 | 说明 |
|--------|------|
| **1. 当前是否为 DPTF 控扇配置** | 若固件为 **EC 全权控扇**`CONFIG_MINIPC_EC_FULL_FAN_CONTROL=y` 且 `CONFIG_DRIVERS_INTEL_DPTF_DISABLE_ACTIVE_FAN=y`DPTF 风扇设备被隐藏_STA=0Windows **不会**调用 \_FSLFAND 仅由 EC 在写 0xFF 后按自身 thermistor 变化。此时“DPTF 没改 FAND”是预期行为。若要验证 DPTF 控扇,需先改为 DPTF 控扇配置并重新刷写。 |
| **2. Windows 是否识别 DPTF 设备** | 设备管理器中查看是否有 **Intel Dynamic Platform and Thermal Framework** 或 ACPI 下的 **INT3400、INT3404** 等。若无 INT3404/DPTF 风扇设备,说明驱动未加载或 ACPI 未暴露DPTF 不会写 FAND。 |
| **3. 是否安装 DPTF 驱动** | 从 Microsoft Update Catalog 搜索 “Intel DPTF” 或 “Dynamic Platform Thermal”或从 OEM如 Acer下载该机型的 DPTF/热管理驱动并安装。未安装时 OS 不会根据 DPTF 表调用 \_FSL。 |
| **4. 电源/热管理策略** | Windows 电源选项中是否有“Intel DPTF”或“平台热管理”相关项部分 OEM 软件会关闭 DPTF 控扇或固定为静音策略,导致不写 FAND。可切换电源方案平衡/高性能)后再观察 FAND。 |
| **5. 负载下观察** | 在确认固件为 DPTF 控扇、且设备管理器中有 INT3404 的前提下,对 CPU 施加负载(如压力测试),每隔数秒读一次 `\_SB.ECT0._FST`。若 FAND 始终不变,可判断为 DPTF 驱动未调用 \_FSL 或策略未生效。 |
### 13.4 小结
- 监视 \_FSL = 轮询读 FAND通过 ECT0._FST 或等效接口)。
- FAND 不变时:先确认是 **EC 控扇** 还是 **DPTF 控扇** 的固件;若为 DPTF 控扇则检查 Windows 是否安装并加载 DPTF 驱动、INT3404 是否存在、电源/热管理策略是否启用 DPTF 控扇。
### 13.5 如何检查 \_SB.ECT0._FST 是否暴露给系统
`\_SB.ECT0` 仅在固件开启 **CONFIG_DRIVERS_INTEL_DPTF_ECTST_FAND_DEBUG=y** 时存在;未开启则 ACPI 里没有该设备,无法读 _FST。
**方法一:直接尝试执行(最直接)**
- **Windows**:安装 [ec-test-app](https://github.com/OpenDevicePartnership/ec-test-app)ectest在**管理员** PowerShell 中执行:
```powershell
ectest -acpi \_SB.ECT0._FST
```
- 若返回数值(如 FAND 0255→ 已暴露。
- 若报错 “object not found” / “method does not exist” / 无法解析路径 → 未暴露或固件未开上述 CONFIG。
- **Linux**:用 ACPI 调试接口(需 root
```bash
# 若内核有 ACPI 调试,可尝试(部分内核未启用)
echo '\_SB.ECT0._FST' > /sys/kernel/debug/acpi/custom_method
cat /sys/kernel/debug/acpi/custom_method
```
或使用 **acpi_call** 等模块/工具调用 ACPI 方法(若已安装)。
**方法二: dump DSDT/SSDT 看是否有 ECT0 与 _FST**
- **Windows**
1. 用 [SSDTTime](https://github.com/corpnewt/SSDTTime) 选 “Dump DSDT” 得到 DSDT.aml或用 [ACPICA acpidump](https://acpica.org/downloads/binary-tools)`acpidump -b -n DSDT` 得到 DSDT.dat改名为 DSDT.aml
2. 用 [iasl](https://acpica.org/downloads/binary-tools) 反编译:`iasl -d DSDT.aml`,得到 DSDT.dsl。
3. 在 DSDT.dsl 中搜索 `ECT0`、`_FST`:若在 `Scope (\_SB)` 下存在 `Device (ECT0)` 且其内有 `Method (_FST, ...)`,则固件已暴露该对象(是否可用还取决于 _STA 等)。
- **Linux**
```bash
sudo cat /sys/firmware/acpi/tables/DSDT > DSDT.aml
iasl -d DSDT.aml
grep -n "ECT0\|_FST" DSDT.dsl
```
**方法三:设备/驱动侧(辅助)**
- **Windows**:设备管理器中查看 ACPI 设备列表,是否有与 “ECT” 或 “DPTF ECT” 相关的设备(名称因 OEM 而异,不一定叫 ECT0
- 若固件未开 `CONFIG_DRIVERS_INTEL_DPTF_ECTST_FAND_DEBUG`DSDT 中不会出现 ECT0方法一、二都会得到“未暴露”的结论。
### 13.6 实测ECT0.\_FSL 写入未生效的情况
- 环境:当前这台 Chromebox 刷入的 coreboot 配置为 **EC 全权控扇**(推测存在 `CONFIG_MINIPC_EC_FULL_FAN_CONTROL=y` 之类),同时打开了 DPTF ECT 调试接口(`CONFIG_DRIVERS_INTEL_DPTF_ECTST_FAND_DEBUG=y`)。
- 实测命令:
```powershell
# 1读当前 FAND
ectest -acpi \_SB.ECT0._FST
# Argument[1] = 0xff EC 自动控扇)
# 2写入 0x80
ectest -acpi \_SB.ECT0._FSL 0x80
# 3再读
ectest -acpi \_SB.ECT0._FST
# Argument[1] 仍为 0xff
```
- 同样逻辑用 `Test_ECT0_FST_FSL.ps1` 自动化验证时,效果一致:
- `[1] Current FAND from _FST: FAND = 0xff`
- `[2] Writing FAND via _FSL(0x80) ...` 执行成功ACPI 返回 Arg0=0x80
- `[3] Read-back FAND after _FSL: FAND = 0xff`,后续轮询 `_FST` 仍为 0xff。
**对 `_FST/_FSL` 返回值的具体解读:**
- **[1] `_FST` = 0xff**
- `_FST` 返回包里的 `Argument[1] = 0xff`,表示 EC 侧 **当前 FAND=0xFF**,即“自动控扇模式”。
- **[2] `_FSL(0x80)` 返回 0x80**
- 这里的 `Argument[0] = 0x80` 只是这次 `_FSL` 调用把参数“原样回显”,说明 ACPI 方法被成功执行,**并不等于 EC 里的 FAND 已经变成 0x80**。
- **[3] 再次 `_FST` 仍然 0xff**
- 再读 `_FST` 时 `Argument[1]` 还是 `0xff`,说明 **EC 看到的 FAND 一直没有从 0xFF 变成 0x80**,要么 `_FSL` 根本没写到 EC.FAND要么写了但被 EC 逻辑立即覆盖回 0xFF。
- **[4] 持续监控 `_FST` 也一直是 0xff**
- 说明在一段时间内 FAND 从未被真正设为 0x80EC 自始至终都工作在自动控扇模式。
**结论(就当前固件配置):**
1. 虽然 ACPI 中存在 `\_SB.ECT0._FST / _FSL`,但 `_FSL` 调用并**没有真正改掉 EC 侧的 FAND 字段**
2. 更可能的实现是coreboot 的 ACPI 里为调试方便加了 `_FST/_FSL` 方法,但在 EC 全权控扇配置下,`\_FSL` 要么只是“回显参数”(`Return(Arg0)`),要么即便临时写入 FAND也被 EC 策略立即覆盖回 0xFF
3. 因为 FAND 始终为 0xFFEC 始终工作在“自动控扇”模式DPTF/ECT0 这条路径**实际处于旁路状态**。
---
*文档由分析过程整理,便于后续改 EC 或排查温控时查阅。*
### 13.6 实测ECT0._FSL 写入 0x80 后 FAND 始终为 0xFF 的根因
- 环境:当前 Chromebox 上已启用 DPTF + ECT0`CONFIG_DRIVERS_INTEL_DPTF_ECTST_FAND_DEBUG=y`),通过 `ECT0._FST/_FSL` 读写 FAND。
- 实测命令(节选自 `logs.txt`