USB论坛
直播中

刘高

11年用户 1039经验值
擅长:嵌入式技术
私信 关注
[问答]

通过I2C总线从源读取所有PDO,但在HPI规范中找不到相应的寄存器,为什么?

我想通过I2C总线从源读取所有PDO,但在HPI规范中找不到相应的寄存器。 我发现可以通过 HPI 实用程序读取它们,所以信息一定在那里。 有人可以请告诉我路吗? 谢谢!

回帖(1)

477289

2025-5-22 16:59:11

通过I2C总线读取PDO(Power Data Objects)时遇到寄存器映射不明确的问题,可能是由于以下原因及解决方案:




关键原因分析




  1. 协议层访问机制



    • PDO信息通常通过动态协议交互(如USB PD/SMBus命令)获取,而非直接映射到固定寄存器。

    • HPI工具可能封装了底层命令(如Get_PDO_Info),而非直接读写寄存器。




  2. 厂商自定义命令



    • 某些设备使用扩展SMBus命令(0x30~0x3F)或VDM(Vendor Defined Messages)传输PDO数据。

    • 例如:发送0x3A命令码触发PDO数据返回。




  3. 分块读取与数据结构



    • PDO可能以多字节块形式返回,需通过I2C Block Read连续读取(如I2C_M_RECV_LEN标志)。




  4. 访问权限控制



    • 部分设备需要先发送解锁序列(如写入密钥到指定寄存器)才能访问PDO信息。






解决方案步骤




  1. 捕获HPI工具的通信流



    • 使用逻辑分析仪(如Saleae)或i2c-tools监听HPI工具的I2C通信。

    • 观察命令码(如0x3A)及数据包结构。




  2. 解析PDO数据格式



    • 典型PDO结构为4字节(32位),例如:
      typedef struct {
      uint8_t voltage;   // 电压(单位:50mV)
      uint8_t current;   // 电流(单位:10mA)
      uint16_t flags;    // 标志位(固定电压/可调、双角色等)
      } PDO;

    • 通过i2c_smbus_read_block_data()读取并解析。




  3. 实现代码示例(Linux I2C)


    #include 
    #include

    int fd = open("/dev/i2c-1", O_RDWR);
    ioctl(fd, I2C_SLAVE, 0x50); // 设备地址

    // 发送PDO读取命令(假设命令码为0x3A)
    uint8_t cmd = 0x3A;
    write(fd, &cmd, 1);

    // 读取4个PDO(每个4字节)
    uint8_t pdo_data[16];
    read(fd, pdo_data, 16);

    // 解析第一个PDO
    PDO pdo1 = {
       .voltage = pdo_data[0],
       .current = pdo_data[1],
       .flags = (pdo_data[2] << 8) | pdo_data[3]
    };



  4. 检查厂商文档或应用笔记



    • 搜索 PDO I2C Protocol,寻找非公开命令参考。

    • 例:TI PD控制器可能使用0x2A-0x2D寄存器分页切换后访问PDO。






调试建议




  • 使用i2c-tools验证


    # 安装工具
    sudo apt-get install i2c-tools

    # 扫描设备地址
    i2cdetect -y 1

    # 尝试读取(假设地址0x50,命令0x3A)
    i2cget -y 1 0x50 0x3A w



  • 参考USB PD规范



    • 查阅《USB Power Delivery Specification》第8.3章,了解PDO数据结构的标准定义。






总结


PDO数据通常通过动态协议交互而非固定寄存器访问。通过逆向HPI工具流量、实现SMBus命令交互,并参考设备特定文档,可成功读取PDO信息。若仍遇困难,建议直接联系芯片厂商获取技术支持。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分