主题中讨论的其他器件: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.


