You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派关机时I2C总线异常:内核模块与Arduino通信故障

问题分析与解决方案

核心问题

为树莓派编写的内核模块,通过pm_power_off函数在关机阶段向I2C总线的Arduino发送指令,地址发送并得到ACK后总线进入异常状态;模块加载/卸载、Python测试脚本均正常,仅关机场景出现问题。

可能的原因

  • 关机阶段硬件资源状态变化:系统关机时,内核会逐步关闭外设时钟、切断部分电源域,I2C控制器可能已进入低功耗准备状态,此时发起传输会因硬件时序无法保证导致总线状态紊乱。
  • pm_power_off执行时机过晚:该函数被调用时,系统已进入关机流程后期,部分子系统(如I2C驱动的底层资源)可能已被释放或处于不稳定状态,直接调用I2C读写会因资源不可用引发总线异常。
  • I2C时序兼容性问题:关机阶段树莓派时钟频率可能波动,与Arduino Uno的I2C采样时序不匹配,即使地址ACK正常,后续数据传输的时序偏差也会导致总线锁死。

解决方案

  1. 提前执行I2C操作
    不要直接在pm_power_off中执行传输,而是通过注册syscore_ops,在系统关机的更早阶段(子系统尚未关闭)完成指令发送。示例代码:

    static void my_shutdown_notify(void) {
        // 此处执行I2C写入操作
        i2c_smbus_write_byte_data(client, REG_SHUTDOWN, SHUTDOWN_CMD);
    }
    
    static struct syscore_ops my_syscore_ops = {
        .shutdown = my_shutdown_notify,
    };
    
    static int __init my_module_init(void) {
        // 其他初始化逻辑
        register_syscore_ops(&my_syscore_ops);
        return 0;
    }
    
    static void __exit my_module_exit(void) {
        unregister_syscore_ops(&my_syscore_ops);
        // 其他清理逻辑
    }
    
  2. 强制恢复I2C总线状态
    在传输后检测总线状态,若异常则发送总线恢复序列(通过SCL产生9个时钟脉冲释放SDA),强制总线回到空闲状态。示例代码:

    void i2c_bus_recover(struct i2c_adapter *adap) {
        struct i2c_algo_bit_data *bit_data = adap->algo_data;
        int i;
    
        // 初始化引脚状态
        bit_data->setsda(adap, 1);
        bit_data->setscl(adap, 1);
        msleep(1);
    
        // 生成9个时钟脉冲
        for (i = 0; i < 9; i++) {
            bit_data->setscl(adap, 0);
            msleep(1);
            bit_data->setscl(adap, 1);
            msleep(1);
        }
    
        // 发送停止条件
        bit_data->setsda(adap, 0);
        msleep(1);
        bit_data->setscl(adap, 1);
        msleep(1);
        bit_data->setsda(adap, 1);
        msleep(1);
    }
    

    在关机触发的I2C操作完成后调用该函数。

  3. 降低I2C总线速度
    将树莓派I2C总线速度降低至10kHz等低速档位,减少关机阶段时钟波动对时序的影响,提升兼容性。初始化时设置:

    adap->bus_freq = 10000; // 10kHz
    
  4. 重新初始化I2C控制器
    在关机阶段执行传输前,调用I2C适配器的pre_xfer回调或直接重新配置时钟,确保控制器处于正常工作状态。

额外说明

  • pm_power_off_prepare在Linux内核5.18后被移除,替代方案为syscore_ops或register_power_off_handler(后者执行时机晚于前者)。
  • 逻辑分析仪采样问题:250MHz重复采样、200MHz漏采属于采样率与信号频率不匹配的测量误差,建议使用I2C时钟整数倍的采样率(如100kHz时钟对应1MHz采样),保证结果准确。

内容的提问来源于stack exchange,提问作者IlNerdChuck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 08:43:29