news 2026/5/2 21:24:43

OpenBMC与ASPEED HWMON驱动集成方法论讲解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenBMC与ASPEED HWMON驱动集成方法论讲解

OpenBMC中ASPEED HWMON驱动集成实战指南:从设备树到sysfs的全链路解析

你有没有遇到过这样的场景?BMC系统已经跑起来了,IPMI也能连上,但风扇转速读出来一直是0 RPM——明明硬件接好了,信号也测过是正常的。或者更糟,PWM调速完全没反应,风扇要么狂转,要么干脆不转。

别急,这大概率不是你的代码写错了,而是ASPEED HWMON驱动和设备树之间的“最后一公里”没打通

在OpenBMC开发中,尤其是基于AST2500/AST2600这类主流BMC SoC时,aspeed-pwm-tach驱动看似简单,实则暗藏玄机。它不像普通GPIO那样“写个1就亮”,它的稳定运行依赖于设备树、时钟、引脚复用、内核HWMON框架等多个环节的精密配合。

本文不讲空泛理论,我们直接下探到寄存器级,手把手拆解如何让ASPEED的硬件监控模块真正“活”起来,并为上层OpenBMC服务提供可靠数据支撑。


为什么非要用ASPEED原生HWMON?软件轮询不行吗?

先说结论:能用硬件就别靠软件

很多开发者初期会尝试用GPIO + 定时器去读风扇Tach信号——比如每100ms读一次电平变化,算出RPM。听起来可行,但在生产级BMC系统中,这种做法有三大硬伤:

  1. 精度差:软件定时不准,尤其在系统负载高时,采样周期抖动大;
  2. CPU占用高:多个风扇+温度轮询会让kworker线程忙个不停;
  3. 无法闭环控制:做不到PWM输出与Tach输入的硬件联动。

而ASPEED的ast-hwmon模块恰恰解决了这些问题。它内置了:
- 独立的PWM发生器(支持25kHz高频输出);
- Tach计数器(可自动捕获脉冲周期);
- 可配置的采样定时器(无需CPU干预);
- 中断机制(风扇堵转告警);

换句话说,一旦配置正确,这个模块就能在后台默默工作,几乎不消耗CPU资源


设备树:驱动能否加载的“生死状”

我们先来看一个真实案例:某客户反馈aspeed-pwm-tach驱动始终加载失败,dmesg里只有一行冰冷的日志:

aspeed-pwm-tach: probe of pwm_tach failed with error -2

错误码-2ENOENT—— 资源不存在。问题出在哪?设备树配置漏了关键字段

下面是修复前后的对比:

❌ 错误配置(缺少clocks)

&pwm_tach { compatible = "aspeed,ast2600-pwm-tach"; reg = <0x1e785000 0x500>; interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; fan@0 { reg = <0>; aspeed,fan-tach-src = <0>; aspeed,pwm-output = <0>; }; };

看起来结构完整,但缺了最关键的一环:时钟使能

ASPEED的外设模块大多默认是断电状态,必须通过clocks属性通知内核打开门控时钟,否则寄存器访问全部无效——相当于你试图操作一个没通电的芯片。

✅ 正确配置(补全clocks与pinctrl)

&pwm_tach { compatible = "aspeed,ast2600-pwm-tach"; reg = <0x1e785000 0x500>; interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; clocks = <&syscon ASPEED_CLK_GATE_PWMCLK>; clock-names = "clk"; resets = <&syscon ASPEED_RESET_PWM>; pinctrl-names = "default"; pinctrl-0 = <&pwm0 &tach0>; fan@0 { reg = <0>; aspeed,fan-tach-src = <0>; aspeed,pwm-output = <0>; }; };

关键点说明:

字段作用常见坑点
compatible匹配驱动,必须严格对应写成aspeed,pwm-tach会匹配失败
reg寄存器基址AST2600是0x1e785000,AST2400不同
clocks使能模块时钟忘记添加会导致probe失败或kernel hang
pinctrl-0设置引脚复用若未配置,PWM信号可能被当作GPIO

💡 提示:可以用cat /sys/kernel/debug/pinctrl/*/pingroups查看当前pinmux状态,验证是否生效。


驱动内部发生了什么?一步步看probe流程

当设备树正确后,Linux内核就会调用aspeed_pwm_tach_probe()函数。我们来拆解它的核心逻辑:

第一步:获取资源并映射寄存器

res = platform_get_resource(pdev, IORESOURCE_MEM, 0); pt->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(pt->base)) return PTR_ERR(pt->base);

这里将物理地址0x1e785000映射为虚拟地址,后续所有寄存器读写都通过pt->base进行。

第二步:开启时钟

pt->clk = devm_clk_get(&pdev->dev, "clk"); if (IS_ERR(pt->clk)) return PTR_ERR(pt->clk); ret = clk_prepare_enable(pt->clk); if (ret) { dev_err(&pdev->dev, "failed to enable clk\n"); return ret; }

如果这一步失败(比如设备树没写clocks),clk_get返回错误,probe直接退出。

第三步:复位模块

reset_control_assert(rst); udelay(10); reset_control_deassert(rst);

确保模块处于干净初始状态。

第四步:初始化PWM与Tach通道

/* 设置PWM频率为25kHz */ aspeed_pwm_set_freq(pt, 0, 25000); /* 启用TACH0采样 */ aspeed_tach_enable(pt, 0);

这些操作会写入对应的控制寄存器,例如:
- PWM频率由PT0CR寄存器设置;
- Tach使能位在TACH_CTRL中;

你可以用devmem 0x1e785000直接查看这些寄存器值,确认配置是否生效。

第五步:注册到HWMON子系统

pt->hwmon_dev = devm_hwmon_device_register_with_info( &pdev->dev, "aspeed", pt, &aspeed_hwmon_ops, NULL);

这是最关键的一步。成功后,会在/sys/class/hwmon/下生成目录,比如hwmon0


HWMON接口暴露:用户空间怎么读数据?

注册成功后,系统会自动生成标准sysfs节点:

/sys/class/hwmon/hwmon0/ ├── name → aspeed ├── fan1_input → 17850 (RPM) ├── pwm1 → 128 (占空比,0~255) └── subsystem -> ../../../../class/hwmon

这些文件的背后,是由你在驱动中定义的hwmon_ops回调函数支撑的。

如何实现read回调?

static int aspeed_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { struct aspeed_pwm_tach *pt = dev_get_drvdata(dev); switch (type) { case hwmon_fan: if (attr == hwmon_fan_input) { *val = read_tach_count(pt, channel); // 从寄存器读脉冲 return 0; } break; case hwmon_pwm: if (attr == hwmon_pwm_output) { *val = pt->pwm_duty[channel]; // 返回当前设定值 return 0; } break; } return -EOPNOTSUPP; }

当你执行cat /sys/class/hwmon/hwmon0/fan1_input时,内核就会调用这个函数,返回实际测量值。

⚠️ 注意:read_tach_count()并不是每次都读硬件——有些版本的驱动使用定时器定期刷新缓存值,避免频繁访问寄存器。


常见问题排查手册:五个高频“踩坑”场景

🛑 场景一:fanX_input 永远是0

可能原因
- Tach通道未使能(检查设备树aspeed,fan-tach-src);
- 引脚复用错误(PWM/Tach引脚被当成GPIO用了);
- 风扇信号未接入或损坏;
- 寄存器超时(tach_timeout设置太短);

调试命令

# 查看是否有有效计数 devmem 0x1e785100 # TACH_COUNT_REG0 dmesg | grep tach # 是否有timeout日志

🛑 场景二:pwmX 写入无反应

典型表现

echo 255 > /sys/class/hwmon/hwmon0/pwm1 # 但风扇速度不变

排查步骤
1. 检查pinctrl是否启用PWM模式;
2. 使用示波器测量对应引脚是否有PWM波形;
3. 确认风扇是否支持PWM调速(有些是电压调速);
4. 检查clk是否enable:
bash cat /sys/kernel/debug/clk/clk_summary | grep pwm

🛑 场景三:驱动加载时报 -EBUSY

错误日志

aspeed-pwm-tach: resource busy

原因:寄存器地址范围已被其他驱动占用。

解决方法
- 检查是否有重复定义的node;
- 确保没有其他模块(如custom-gpio)占用了PWM资源;


上层应用如何消费这些数据?phosphor-hwmon 的角色

在OpenBMC中,光有sysfs还不够。我们需要把这些原始数据变成可管理的传感器实体。

这就是phosphor-hwmon的作用。它是一个守护进程,会定期扫描所有hwmon节点,并做以下事情:

  1. 解析namelabel等属性;
  2. fan1_input映射为 D-Bus 接口xyz.openbmc_project.Sensor.Fan;
  3. 生成 IPMI SDR 记录,供远端KVM/IPMI客户端查询;
  4. 支持阈值监控与告警上报;

举个例子:

{ "Name": "fan1", "Unit": "rpm", "Value": 17850, "Scale": 0, "Thresholds": { "LowerCritical": 500 } }

这样,WebUI、REST API、SNMP都能统一看到风扇状态。


高阶技巧:动态更新与调试建议

动态修改PWM占空比(测试用)

echo 1 > /sys/class/hwmon/hwmon0/pwm1_enable # 0=manual, 1=auto echo 180 > /sys/class/hwmon/hwmon0/pwm1 # 设置占空比

注意:只有当pwm1_enable=0时才能手动写入。

开启HWMON调试日志

在内核启动参数加:

module.aspeed_pwm_tach.debug=1

然后通过dmesg查看详细操作流程。

使用device tree overlay热插拔传感器(实验性)

虽然生产环境不推荐,但在开发阶段可以利用overlay动态添加新风扇定义,实现“热插拔”式调试。


写在最后:稳定性比功能更重要

在BMC系统中,风扇控制是安全相关的功能。即使软件崩溃,也不能让服务器因散热失效而烧毁。

因此,在设计时务必考虑:

  • 硬件默认PWM输出是否设为“全速”?
  • 是否设置了最小安全转速?
  • 断网或BMC宕机时,风扇能否保持运转?

ASPEED芯片本身支持一些安全机制,比如:
- 独立的硬件看门狗控制PWM;
- 备用固件模式下仍可维持基本散热;

合理利用这些特性,才能构建真正可靠的BMC系统。

如果你正在做OpenBMC移植或定制开发,不妨现在就去检查一下你的设备树和dmesg日志——也许那个一直读不到的风扇,只差一行clocks配置。

欢迎在评论区分享你遇到过的HWMON“诡异bug”,我们一起排雷。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 22:55:59

image2lcd导出配置详解:适用于单色屏的参数设置

图像转码不翻车&#xff1a;搞懂 image2lcd 的单色屏配置逻辑你有没有遇到过这种情况——辛辛苦苦在 Photoshop 里设计好一个 Logo&#xff0c;导入image2lcd转成数组&#xff0c;烧进 STM32 后却发现 OLED 上显示的图像是上下颠倒、左右反了、还缺胳膊少腿&#xff1f;别急&am…

作者头像 李华
网站建设 2026/5/1 10:48:55

OpenMV与霍尔传感器测速的硬件设计实例

用OpenMV和霍尔传感器打造高鲁棒性测速系统&#xff1a;从原理到实战的完整设计指南在智能小车、AGV导航或工业传送带监控中&#xff0c;速度是控制系统的生命线。传统的编码器虽然精度高&#xff0c;但在粉尘、油污环境下容易失效&#xff1b;纯视觉方案又受限于光照变化与计算…

作者头像 李华
网站建设 2026/5/2 14:48:05

VHDL课程设计大作业中的矩阵键盘扫描FPGA方案

用FPGA玩转矩阵键盘&#xff1a;从VHDL课程设计到真实系统控制的完整实践 你有没有在做 VHDL课程设计大作业 时&#xff0c;面对一个看似简单的“44按键”却无从下手&#xff1f;明明只是按下一个键&#xff0c;仿真波形里却跳出了七八次触发&#xff1b;扫描逻辑写了一堆&am…

作者头像 李华
网站建设 2026/4/25 19:08:22

Vitis使用教程:优化卷积运算的FPGA实践

如何用Vitis把卷积算得又快又省&#xff1f;FPGA加速实战全解析你有没有遇到过这样的问题&#xff1a;在边缘设备上跑一个轻量级CNN模型&#xff0c;CPU占用率直接飙到90%&#xff0c;帧率掉到个位数&#xff0c;功耗还高得离谱&#xff1f;这几乎是每个做嵌入式AI开发的人都踩…

作者头像 李华
网站建设 2026/5/2 19:21:28

Vitis使用教程:从零实现AI模型FPGA部署

从零开始&#xff1a;用Vitis把AI模型部署到FPGA上&#xff0c;我走过的每一步都算数 最近在做边缘AI推理项目时&#xff0c;被一个现实问题卡住了&#xff1a;GPU功耗太高&#xff0c;端侧跑不动&#xff1b;云端延迟又太大&#xff0c;实时性扛不住。于是我把目光转向了FPGA…

作者头像 李华
网站建设 2026/4/23 18:48:51

Xilinx官网License申请实操:超详细版图文教程

手把手教你搞定 Vivado License&#xff1a;从零开始的实战配置指南 你是不是也曾在打开 Vivado 时&#xff0c;突然弹出一个红色警告&#xff1a;“License checkout failed”&#xff1f; 或者刚建好工程、准备综合&#xff0c;却发现 IP 核用不了&#xff0c;提示“Featur…

作者头像 李华