Linux设备树中MCP2518FD的时钟配置:从0.00MHz到40.00MHz
Linux设备树中MCP2518FD的时钟配置:从0.00MHz到40.00MHz
[!TIP] 午夜码农的咏叹调 啊,键盘上的勇士,夜深人静战bug, 代码如顽敌,纠缠至天明将近。 眼皮如铅重,咖啡已成空杯, 仅剩三时安眠,闹钟已张开巨口。 然此时灵光乍现,博客须发于世! 笑看睡眠债堆积,技术火炬永不灭。 程序猿啊,程序猿,人生如代码,debug永无止境!
问题背景
在使用MCP2518FD CAN控制器时,通过dmesg查看驱动初始化日志,发现了一个值得关注的细节:
[ 3.207754] mcp251xfd spi0.0 can0: MCP2518FD rev15.15 (-RX_INT -PLL -MAB_NO_WARN +CRC_REG +CRC_RX +CRC_TX +ECC -HD o:0.00MHz c:40.00MHz m:0.60MHz rs:0.60MHz es:0.59MHz rf:0.60MHz ef:0.59MHz) successfully initialized.
注意其中的 o:0.00MHz,这表示驱动检测到的外部晶振(Oscillator)频率为0,而实际硬件使用的是40MHz晶振。这种不匹配可能会导致时钟相关的潜在问题。
时钟参数解读
日志中的时钟相关参数含义如下:
| 参数 | 全称 | 含义 |
|---|---|---|
| o: | Oscillator | 外部晶振频率,驱动识别到的基准时钟源 |
| c: | CAN Clock | CAN控制器内核实际运行时钟 |
| m: | Max SPI | SPI总线最大通信频率 |
| rs: | Requested Speed | 设备树中请求的SPI速率 |
| es: | Effective Speed | SPI控制器实际输出的有效速率 |
当 o:0.00MHz 时,说明驱动没有正确识别外部晶振频率。虽然 c:40.00MHz 显示CAN时钟为40MHz,但这可能是驱动使用的默认值或推测值,而非基于正确的晶振配置计算得出。
为什么会出现o:0.00MHz?
原始设备树配置中使用了 clock-frequency 属性:
&spi0 {
status = "okay";
// ... 其他配置 ...
spican0: spican@0 {
compatible = "microchip,mcp2518fd";
reg = <0>;
spi-max-frequency = <100000>;
interrupts-extended = <&porta 10 IRQ_TYPE_LEVEL_LOW 0>;
clock-frequency = <40000000>;
};
};
正确的解决方案
Linux设备树推荐使用 fixed-clock 节点来描述固定频率的时钟源:
// 在根设备树节点 /{ } 中添加
can_osc: can-osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <40000000>;
};
&spi0 {
status = "okay";
clocks = <&scmi_clk GATE_LSP0_SSI_M_WCLK_EN>,
<&scmi_clk GATE_LSP0_SSI_M_PCLK_EN>;
clock-names = "wclk", "pclk";
resets = <&scmi_reset RST_LSP0_SSI_M_WCLK_SW>;
reset-names = "spi";
pinctrl-names = "default";
pinctrl-0 = <&spi0_pinctrl>;
spican0: spican@0 {
compatible = "microchip,mcp2518fd";
reg = <0>;
spi-max-frequency = <100000>;
interrupts-extended = <&porta 10 IRQ_TYPE_LEVEL_LOW 0>;
clocks = <&can_osc>; /* 显式引用时钟节点 */
};
};
关键改进点
- 创建独立的时钟节点:
can_osc作为一个标准的fixed-clock提供者 - 显式引用时钟:通过
clocks = <&can_osc>建立明确的时钟消费关系 - 符合设备树规范:这种方式更容易被[[时钟框架]]([[CCF]])正确处理
修改后的效果
重新编译设备树并启动后,dmesg日志应显示:
[ 3.207754] mcp251xfd spi0.0 can0: MCP2518FD rev15.15 (... o:40.00MHz c:40.00MHz ...) successfully initialized.
此时 o: 参数正确显示为 40.00MHz,表明驱动已正确识别外部晶振频率。
为什么这很重要?
虽然在某些场景下,即使 o:0.00MHz 系统也可能表面上正常工作,但正确配置时钟源具有以下重要意义:
- 波特率计算准确性:CAN控制器需要基于准确的晶振频率计算位时间参数(Bit Timing)
- 时钟同步:确保发送和接收逻辑使用相同的时间基准
- 硬件功能完整性:某些高级功能(如时间戳)依赖准确的时钟源
- 诊断信息可靠性:准确的时钟信息有助于排查其他问题
总结
在配置MCP2518FD等需要外部晶振的SPI CAN控制器时,应该:
- ✅ 使用
fixed-clock节点定义时钟源 - ✅ 通过
clocks属性显式引用时钟 - ✅ 验证dmesg中
o:参数显示正确频率 - ❌ 避免直接使用
clock-frequency属性 - ❌ 避免注释掉关键配置而不替换
这种规范的配置方式不仅能解决当前问题,还能为后续的功能扩展和问题排查打下良好基础。