This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TPS65987D:在 TPS65987D 上加载配置

Guru**** 2385020 points
Other Parts Discussed in Thread: TUSB542, TPS65988, TPS65987D
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1369582/tps65987d-loading-configuration-on-tps65987d

器件型号:TPS65987D
主题中讨论的其他器件:TUSB542TPS65987TPS65988

工具与软件:

在我们的设计中、我们没有用于 TPS65987的 SPI 闪存、而我们将 TUSB542作为 i2c 从器件连接。 我们希望在板启动时通过 i2c 加载 TPS659x 的配置。
我们编写了 u-boot 代码、以通过配置工具和 PTC/PTCd/PTCc 4cc 命令导出"low region" C 头文件来修补 TPS659x。

static int tps_4cc_command(struct udevice *i2c_dev, const char *cmd, const char *data, int len) {
    int ret;
    u8 buf[len+1];

    printf("%s: input data %u bytes: ", cmd, len);

    for(int i = 0; i < len; i++) {
        printf("%02x", data[i]);
    }
    printf("\n");
    if(len) {
        buf[0] = len;
        memcpy(&buf[1], data, len);
        ret = dm_i2c_write(i2c_dev, 0x9, (u8*)data, len);
        if(ret) {
            printf("%s i2c command failed, err %d\n", __func__, ret);
        }
    }

    buf[0] = 5;
    memcpy(&buf[1], cmd, 4);
    ret = dm_i2c_write(i2c_dev, 0x8, buf, 5);
    if(ret) {
        printf("%s i2c command failed, err %d\n", __func__, ret);
    }
    // wait for command buffer to clear, that's how we know the command is done
    int timeout = 10;
    while(timeout != 0) {
        ret = dm_i2c_read(i2c_dev, 0x8, buf, 4);
        if(buf[1] == '!') {
            printf("%s: !CMD (invalid command)\n", cmd);
            return -1;
        }
        if(buf[1] == '\0') {
            break;
        }
        udelay(50000);
        timeout--;
    }
    return ret;
}
#pragma pack(push, 1)
typedef struct PTCq_decode {
    u8  TaskResponse;
    u8  PatchReturnCode;
    u8  PatchLoadingState;
    u8  Reserved_0;
    u16 TotalDataTransferred;
    u16 DevicePatchDataTransferred;
    u16 ApplicationConfigurationDataTransferred;
    u8  DevicePatchState;
    u8  DevicePatchSource;
    u8  ApplicationConfigurationPatchState;
    u8  ApplicationConfigurationPatchSource;
} PTCq_decode_t;

typedef struct PTCs_decode {
    u8  TaskResponse;
    u8  PatchStartStatus;
    u8  DevicePatchStartStatus;
    u8  AppConfigStartStatus;
} PTCs_decode_t;

typedef struct PTCd_decode {
    u8  TaskResponse;
    u8  TransferStatus;
    u8  PatchLoadingState;
    u8  Reserved_0;
    u16 TotalDataTransferred;
    u16 DevicePatchDataTransferred;
    u16 ApplicationConfigurationDataTransferred;
} PTCd_decode_t;

typedef struct PTCc_decode {
    u8  TaskResponse;
    u8  Reserved_0;
    u8  DevicePatchCompleteStatus;
    u8  AppConfigPatchCompleteStatus;
} PTCc_decode_t;

#pragma pack(pop)
#define P(x) do{ if(dec->x) printf(#x": 0x%02x\n",dec->x); } while(0)


static int tps_4cc_result(struct udevice *i2c_dev, const char *cmd, int len)
{
    u8 buf[len+1]; // +1 for null termination of certain string returns
    memset(buf, 0, len+1);
    int ret;
    ret = dm_i2c_read(i2c_dev, 0x9, buf, len);
    if(ret) {
        printf("%s i2c command failed, err %d\n", __func__, ret);
        return -1;
    }
    printf("%s: returns %u bytes, showing %u: ", cmd, buf[0], len);

    // 1st byte is the size of the return, skip it
    for(int i = 1; i < len; i++) {
        printf("%02x", buf[i]);
    }
    printf("\n");
    if (strncmp(cmd, "PTCq", 4) == 0) {
        PTCq_decode_t *dec = (PTCq_decode_t*) &buf[1];
        P(TaskResponse);
        P(PatchReturnCode);
        P(PatchLoadingState);
        P(Reserved_0);
        P(TotalDataTransferred);
        P(DevicePatchDataTransferred);
        P(ApplicationConfigurationDataTransferred);
        P(DevicePatchState);
        P(DevicePatchSource);
        P(ApplicationConfigurationPatchState);
        P(ApplicationConfigurationPatchSource);
    }
    if (strncmp(cmd, "PTCs", 4) == 0) {
        PTCs_decode_t *dec = (PTCs_decode_t*) &buf[1];
        P(TaskResponse);
        P(PatchStartStatus);
        P(DevicePatchStartStatus);
        P(AppConfigStartStatus);
    }
//drop printing the download status
    if (strncmp(cmd, "PTCd", 4) == 0) {
        PTCd_decode_t *dec = (PTCd_decode_t*) &buf[1];
        P(TaskResponse);
        P(TransferStatus);
        P(PatchLoadingState);
        P(Reserved_0);
        P(TotalDataTransferred);
        P(DevicePatchDataTransferred);
        P(ApplicationConfigurationDataTransferred);
    }
    if (strncmp(cmd, "PTCc", 4) == 0) {
        PTCc_decode_t *dec = (PTCc_decode_t*) &buf[1];
        P(TaskResponse);
        P(Reserved_0);
        P(DevicePatchCompleteStatus);
        P(AppConfigPatchCompleteStatus);
    }
    return 0;
}
static int tps_patch(struct udevice *i2c_dev, const char* patch, int len)
{
        int ret;
    const char input = 0x3; // 1 app config, 2 is device patch 0x3 is both
    u8 buf[16];

    tps_4cc_command(i2c_dev, "PTCs", &input, 1);
    tps_4cc_result(i2c_dev, "PTCs", 4);

    for(int i = 0; i < len; i+=64) {
        int size = 64;
        if (len-i < 64) {
            printf(" remainder is %u\n", len-i);
            size = len-i;
        }

        tps_4cc_command(i2c_dev, "PTCd", &patch[i], size);
        tps_4cc_result(i2c_dev, "PTCd", 10);
        printf("wrote %u bytes at %u\n", size, i);
    }

    tps_4cc_command(i2c_dev, "PTCc", NULL, 0);
    tps_4cc_result(i2c_dev, "PTCc", 4);

    return -0;
}

补丁过程通过 PatchLoadingState: 0x0a (成功完成)和 DevicePatchState: 0x06 (不是补丁)完成。
我们希望它同时包含 AppConf 和器件补丁、我们可以通过客户使用寄存器看到配置更新、但我们在这里看不到任何更改。
  1. 我们是否使用了正确的文件进行修补?  tps6598x_lowregion_array[] 屏幕截图所示为生成内容。
  2. 有没有比 TPS65987主机接口 pdf 更详细地介绍补丁创建和编程的文档?
  3. 当补丁文件长度为13372字节时、为什么在 PTCd 命令期间"TotalDataTransfered"不会增加到13372字节? (请参阅日志)
  4. 使用 PTCs 命令、我们可以在补丁文件中指定 AppConf 和器件、两者都指定或不指定。 如何区分配置工具中的应用程序配置和器件补丁? 在补丁文件中提供"none"意味着什么?

e2e.ti.com/.../tps6598x.log

此致、

Tomás Almeida.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Tomas:

    • 您生成的 low region 二进制文件是正确的、这就是在进行修补时应该使用的二进制文件。  
    • 技术参考手册中提供了仅有的用于 PTCx 修补的文档。 很遗憾、我们没有其他文档。
    • 我将检查传输的总数据、然后回复给您。
    • 应用程序配置是 GUI 中的配置设置、而补丁是您可以在 GUI 的"General Settings"页面上看到的基本映像。 您应该选择"两者"、因为生成的二进制文件将组合这两者。 如果未选择其中一个、则 PD 将尝试使用默认配置/补丁。

    器件补丁状态指示"不是补丁"、因此似乎补丁下载不成功。 您是否能够收集显示发生这些 I2C 写入/读取的 I2C 日志? 如果 PD 在下载后报告"不是补丁"、并且传输的总数据与补丁大小不匹配、我怀疑并非所有字节都通过 I2C 正确写入了。

    此致!

    Alex

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Alex、
    感谢您的答复、此后、我设法通过修复上述 C 例程(写入4cc 数据寄存器时没有初始字节中的数据长度)将补丁传输到我们设计中的器件。
    我现在从 PTCc 命令收到"器件补丁加载完成"状态、并从 PTCq 命令收到"PatchReturnCode:0x0"和"PatchLoadingState:0xA (补丁过程已成功完成)"。
    然而,我仍在接受 30030000a2060000引导标志女巫的指示 Patch Download Error  PTCq 报告  ApplicationConfigurationState: 0x08 (Application Configuration Patch Error)
    因此、看起来没有应用程序配置已满负载。
    即使使用我可以在应用程序自定义工具中生成的最简单的补丁文件、也会发生此错误、方法是依次按"New Project -> TPS65987DDH -> Standard (Recommended)->仅 UFP -> Save Binary -> Low Region (Minimal headers)。
    1. 根据您写入的内容(以及我对寄存器的探测)、似乎没有 SPI 闪存时器件处于 PTCH 状态并且没有默认 ROM 固件、是正确的吗? 无论我选择何种"基本映像"、"Device Info"寄存器似乎包含"TPS65988 HW0030 FWF707.10.00 ZACE1"、为什么会这样?
    2. 尽管与端口1 i2c 地址通信、似乎只有端口2的客户使用字集反映在0x6寄存器中。 为什么会这样? 端口2的其他哪些设置也应用于端口1?
    3. 如何 Application Configuration Patch Error 进行进一步调试?

    此致、

    Tomás Almeida.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Tomas:

    1.) 正确、没有 SPI 闪存、PD 无法加载固件、并且将处于半禁用 PTCH 状态。 除了 TPS65987D 中的引导加载程序之外、没有默认的 ROM 固件。 按您尝试执行的方式修补 PD 控制器将启用 PD、而无需从闪存加载固件、因为固件会直接修补到 PD 的 SRAM。 器件信息寄存器是 TPS65987D 上的已知错误、无法遗憾地使用新刷写的固件进行更新。

    2.) 这不应该发生。 您可以向我发送 EC 写入端口1的客户使用寄存器的 I2C 日志以及端口2中显示的数据吗? 对于任何寄存器、都不应发生这种情况。

    3.) 为了进一步调试、我们需要验证补丁固件数据的 I2C 传输是否从开始到结束正确发生。 除了您报告的补丁状态之外、PD 寄存器本身可以告诉我们的信息有限。 您是否可以捕获 I2C1/2数据、显示 EC 写入 PD 控制器的情况? 您是否还可以同时包含来自 PD 控制器的 LDO_3V3输出的数字捕获? 我将查看日志并检查所有内容。  

    此致!

    Alex

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Alex、


    感谢您的答复。 既然大家都注意到了、基于某种原因、我们所使用的应用配置有两个端口、而我们的芯片只支持一个端口、我们就已经开始使用新的配置、解决了问题2。


    芯片通电时 LDO_3V3会被拉高。 附件是 修补过程中写入的 I2C 字节和返回状态的日志、但您可能需要示波器跟踪?

    我们还进一步了解了 ApplicationConfigurationPatchState 错误、正如我们在以下帖子中发现的: https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1200098/tps65987d-tps65987d-custom-board-without-external-flash。 

    我们在 BP_NoResponse 安全配置引导模式中配置了芯片、并且没有意识到 这意味着无论在此模式下进行何种配置、端口电源路径都将被禁用!  通过 Re 搭接到其中一种"无限等待"模式的效果要好得多、我们现在可以看到正在为 DFP/UFP 源协商 PDO、以及 为这些电源模式配置了 I2C 从站稳压器。

    修补过程仍然会返回 ApplicationConfigurationPatchState = Error 、但在修补过程完成后、所选的配置似乎会被芯片反映出来、包括 在协商源 PDO 时向稳压器发送必要的 I2C 消息。
    我们仍在验证我们的设计、但我们现在正在取得进展。

    I2C 日志:

    e2e.ti.com/.../patch.log

    此致、

    Tomás Almeida.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Tomas:

    除了  ApplicationConfigurationPatchState 错误外、I2C 数据日志看起来正常。 补丁数据的所有13376字节都被传输到 PD。 我解码了启动标志、没有报告补丁加载错误、这很好。 由于 TPS65987D 在补丁加载完成后正常工作、因此这似乎不是功能问题。 我确实建议您尝试一些操作、这样可以清除错误。 PD 在引导标志寄存器(在下方解码)中报告、PD 的 SPI_MISO 引脚在引导时未接地、在这种情况下会使 PD 检测到是否存在 SPI 闪存。 PD 尝试从 SPI 闪存读取、并报告失败。 您能否将此 SPI_MISO 引脚接地并再次尝试执行补丁过程?  

    此致!

    Alex

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Alex、

    将 SPI_MISO 引脚接地确实清除了引导标志、但  ApplicationConfigurationPatchState 仍然相同。

    此致、

    Tomás Almeida.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Tomas:

    我看了一下 TPS65987D 固件、发现 PTCq 响应数据中有几位与 TPS65987D 技术参考手册不匹配。 请参阅0x09数据寄存器中 PTCq 响应的正确字节13位映射:

    从上表中 PTCq 响应的 ApplicationConfigurationPatchState 字段(字节13)可以看到、读取的0x08值实际上表示应用程序配置补丁加载成功。 您应该会看到0x08。 0x08被错误地映射到技术参考手册中的一个错误。 我们将努力改变这一状况。 感谢您指出这一点、我们对您的意见与建议深表歉意。

    此致!

    Alex