1. Rockchip PWM风扇热管理机制解析
在嵌入式Linux系统中,PWM风扇控制是一个典型的硬件交互场景。Rockchip平台通过设备树配置和内核驱动实现了完整的温度-PWM联动机制。这套系统主要由三部分组成:
- 设备树中的温度阈值与PWM参数配置
- 内核驱动中的热事件通知框架
- PWM输出硬件控制器
当SoC温度传感器检测到温度变化时,会通过thermal子系统触发通知链,最终调用我们注册的PWM调节函数。整个过程实现了从温度采集到风扇转速控制的全自动闭环管理。
关键点:Rockchip的温度阈值配置采用毫摄氏度单位,在设备树中70000表示70℃阈值。这种设计避免了浮点运算,提高了内核执行效率。
2. 设备树配置详解
2.1 基础参数定义
标准的Rockchip PWM风扇设备树节点包含以下核心参数:
dts复制pwm-fan {
compatible = "pwm-fan";
pwms = <&pwm1 0 10000 0>; // PWM控制器、通道、周期(ns)、极性
cooling-levels = <0 100 200 255>; // 4级转速对应占空比
rockchip,temp-trips = <
50000 0 // 50℃时切到cooling-levels[0]
60000 1 // 60℃时切到cooling-levels[1]
70000 2 // 70℃时切到cooling-levels[2]
80000 3 // 80℃时切到cooling-levels[3]
>;
};
参数说明:
pwms:指定使用的PWM控制器和通道,10000ns对应10kHz PWM频率cooling-levels:定义4级转速对应的PWM占空比(0-255)temp-trips:温度阈值与cooling-levels索引的映射关系
2.2 多风扇协同配置
对于需要多个风扇协同工作的场景,设备树支持定义复合控制策略:
dts复制fan-cluster {
fans = <&pwm_fan0 &pwm_fan1>;
cluster-levels = <0 50 100>; // 整体负载级别
fan-levels = <
0 0 0 // 负载0时两个风扇都停止
1 30 20 // 负载1时风扇1=30%,风扇2=20%
2 100 80 // 负载2时全速运行
>;
};
3. 内核驱动实现剖析
3.1 关键数据结构
驱动核心数据结构包含三个关键组件:
c复制struct pwm_fan_ctx {
struct device *dev;
struct pwm_device *pwm;
struct thermal_cooling_device *cdev;
struct notifier_block thermal_nb;
int *thermal_trips; // 温度阈值数组
u8 *cooling_levels; // 冷却级别数组
int cooling_state; // 当前冷却状态
};
3.2 热通知注册流程
pwm_fan_register_thermal_notifier函数完整实现如下:
c复制static int pwm_fan_register_thermal_notifier(struct device *dev,
struct pwm_fan_ctx *ctx)
{
int ret;
// 1. 从设备树获取温度阈值配置
ret = pwm_fan_get_thermal_trips(dev, "rockchip,temp-trips",
&ctx->thermal_trips);
if (ret)
return ret;
// 2. 初始化通知块
ctx->thermal_nb.notifier_call = pwm_fan_thermal_notify;
// 3. 注册到thermal通知链
ret = rockchip_register_thermal_notifier(&ctx->thermal_nb);
if (ret) {
dev_err(dev, "Failed to register thermal notifier\n");
kfree(ctx->thermal_trips);
return ret;
}
return 0;
}
3.3 温度回调处理
当温度跨越阈值时触发的核心处理函数:
c复制static int pwm_fan_thermal_notify(struct notifier_block *nb,
unsigned long trip, void *data)
{
struct pwm_fan_ctx *ctx = container_of(nb, struct pwm_fan_ctx, thermal_nb);
int i, level = 0;
// 确定当前温度对应的冷却级别
for (i = 0; i < ctx->num_trips; i++) {
if (trip >= ctx->thermal_trips[i])
level = i;
else
break;
}
// 避免不必要的PWM更新
if (level == ctx->cooling_state)
return NOTIFY_OK;
// 更新PWM输出
pwm_fan_set_cur_state(ctx, level);
ctx->cooling_state = level;
return NOTIFY_OK;
}
4. 实战调试技巧
4.1 常见问题排查
-
风扇不启动:
- 检查
/sys/class/thermal/下是否生成cooling_device - 使用
i2cdetect确认温度传感器正常 - 用示波器测量PWM引脚是否有输出
- 检查
-
转速控制不线性:
bash复制# 查看当前thermal zone状态 cat /sys/class/thermal/thermal_zone*/temp # 手动设置冷却状态测试 echo 3 > /sys/class/thermal/cooling_device0/cur_state -
设备树解析失败:
- 使用
dtc -I fs /proc/device-tree导出完整设备树 - 确认
rockchip,temp-trips属性格式正确
- 使用
4.2 性能优化建议
-
温度采样间隔:
c复制// 在thermal_zone设备树节点添加采样参数 polling-delay = <1000>; // 1秒采样间隔 polling-delay-passive = <2000>; // 被动模式2秒间隔 -
PWM频率选择:
- 普通风扇:10-25kHz
- 服务器风扇:5-10kHz
- 避免接近风扇共振频率(通常20-30kHz区间)
-
温度迟滞处理:
c复制// 在notify函数中添加5℃迟滞 if (abs(trip - last_trip) < 5000) return NOTIFY_OK;
5. 高级功能扩展
5.1 动态调参接口
通过sysfs实现运行时参数调整:
c复制static ssize_t temp_trips_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
int *new_trips, ret;
// 解析输入字符串格式"50000:0,60000:1"
ret = parse_temp_trips(buf, &new_trips);
if (ret)
return ret;
mutex_lock(&ctx->lock);
kfree(ctx->thermal_trips);
ctx->thermal_trips = new_trips;
mutex_unlock(&ctx->lock);
return count;
}
5.2 智能转速算法
实现基于PID控制的动态调速:
c复制static void pwm_fan_pid_control(struct pwm_fan_ctx *ctx)
{
int err = target_temp - current_temp;
ctx->integral += err;
if (ctx->integral > INTEGRAL_LIMIT)
ctx->integral = INTEGRAL_LIMIT;
int derivative = err - ctx->last_err;
ctx->last_err = err;
int output = KP * err + KI * ctx->integral + KD * derivative;
output = clamp(output, 0, MAX_PWM);
pwm_fan_set_pwm(ctx, output);
}
6. 硬件设计注意事项
-
电路保护设计:
- 必须添加反电动势二极管(如1N4148)
- PWM信号线建议串联100Ω电阻
- 对噪声敏感场景需要添加RC滤波(典型值:100Ω+0.1μF)
-
风扇选型参数:
参数 推荐值 说明 启动电压 ≤标称电压60% 确保低温启动可靠 最大电流 留有30%余量 考虑堵转电流 PWM响应时间 ≤100ms 影响控温精度 -
布线规范:
- PWM走线远离高频信号(如DDR、时钟线)
- 地线尽量短且粗
- 避免与模拟信号平行走线
