主题中讨论的其他器件:TUSB542、 TPS65987、 TPS65988、
工具与软件:
在我们的设计中、我们没有用于 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 和器件补丁、我们可以通过客户使用寄存器看到配置更新、但我们在这里看不到任何更改。
- 我们是否使用了正确的文件进行修补?
tps6598x_lowregion_array[]
屏幕截图所示为生成内容。 - 有没有比 TPS65987主机接口 pdf 更详细地介绍补丁创建和编程的文档?
- 当补丁文件长度为13372字节时、为什么在 PTCd 命令期间"TotalDataTransfered"不会增加到13372字节? (请参阅日志)
- 使用 PTCs 命令、我们可以在补丁文件中指定 AppConf 和器件、两者都指定或不指定。 如何区分配置工具中的应用程序配置和器件补丁? 在补丁文件中提供"none"意味着什么?
此致、
Tomás Almeida.