
在使用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: | ||
| c: | ||
| m: | ||
| rs: | ||
| es: |
当 o:0.00MHz 时,说明驱动没有正确识别外部晶振频率。虽然 c:40.00MHz 显示CAN时钟为40MHz,但这可能是驱动使用的默认值或推测值,而非基于正确的晶振配置计算得出。
原始设备树配置中使用了 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> 建立明确的时钟消费关系重新编译设备树并启动后,dmesg日志应显示:
[ 3.207754] mcp251xfd spi0.0 can0: MCP2518FD rev15.15 (... o:40.00MHz c:40.00MHz ...) successfully initialized.
此时 o: 参数正确显示为 40.00MHz,表明驱动已正确识别外部晶振频率。
虽然在某些场景下,即使 o:0.00MHz 系统也可能表面上正常工作,但正确配置时钟源具有以下重要意义:
在配置MCP2518FD等需要外部晶振的SPI CAN控制器时,应该:
fixed-clock 节点定义时钟源clocks 属性显式引用时钟o: 参数显示正确频率clock-frequency 属性这种规范的配置方式不仅能解决当前问题,还能为后续的功能扩展和问题排查打下良好基础。