你好
我司使用TMS320C5535AZAY10發生錯誤
現象:機率性讀取DDR5 SPD時發生錯誤,從示波器上來看,發現當讀取錯誤發生時,中間有多插入Stop訊號(紅圈處),初步懷疑是此stop所造成。
fw code 如附件。
應用環境:SPD燒入治具

麻煩協助確認問題,或FW code部分建議修正。
謝謝
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.
你好
我司使用TMS320C5535AZAY10發生錯誤
現象:機率性讀取DDR5 SPD時發生錯誤,從示波器上來看,發現當讀取錯誤發生時,中間有多插入Stop訊號(紅圈處),初步懷疑是此stop所造成。
fw code 如附件。
應用環境:SPD燒入治具

麻煩協助確認問題,或FW code部分建議修正。
謝謝
#include <stdio.h>
#include "ts_i2c.h"
#define CSL_I2C_SPDHUB_ADDR (0x50)
CSL_Status ts_i2c_init()
{
CSL_I2cSetup i2cSetup;
CSL_Status status;
status = i2c_base_init(CSL_I2C0);
if (status != CSL_SOK)
{
printf("i2c_base_init Failed!!\n");
return status;
}
// Setup I2C module
i2cSetup.addrMode = CSL_I2C_ADDR_7BIT;
i2cSetup.bitCount = CSL_I2C_BC_8BITS;
i2cSetup.loopBack = CSL_I2C_LOOPBACK_DISABLE;
i2cSetup.freeMode = CSL_I2C_FREEMODE_DISABLE;
i2cSetup.repeatMode = CSL_I2C_REPEATMODE_DISABLE;
i2cSetup.ownAddr = CSL_I2C_OWN_ADDR;
i2cSetup.sysInputClk = CSL_I2C_SYS_CLK;
i2cSetup.i2cBusFreq = CSL_I2C_BUS_FREQ;
status = i2c_base_setup(&i2cSetup);
if (status != CSL_SOK)
{
printf("i2c_base_setup Failed!!\n");
return status;
}
return CSL_SOK;
}
/*
* MR11 [3] = 1: 2 bytes addressing for SPD5 Hub device memory.
*/
CSL_Status spd5hub_read_spd(Uint16 offset, Uint16 length, Uint16 *data)
{
CSL_Status status;
if (offset > 0x03FF)
{
return CSL_ESYS_INVPARAMS;
}
Uint16 block = offset / 64;
Uint16 start = offset % 64;
Uint16 buf[2];
buf[0] = start | 0x80 | ((block & 0x01) << 6);
buf[1] = start >> 1;
status = i2c_base_read(CSL_I2C_SPDHUB_ADDR, buf, 2, data, length);
if (status != CSL_SOK)
{
return status;
}
return CSL_SOK;
}
CSL_Status spd5hub_write_spd(Uint16 offset, Uint16 length, Uint16 *data)
{
CSL_Status status;
if (offset > 0x03FF)
{
return CSL_ESYS_INVPARAMS;
}
Uint16 block = offset / 64;
Uint16 start = offset % 64;
Uint16 buf[64];
Uint16 i;
buf[0] = start | 0x80 | ((block & 0x01) << 6);
buf[1] = start >> 1;
for (i = 0; i < length; i++)
{
buf[i + 2] = data[i];
}
status = i2c_base_write(CSL_I2C_SPDHUB_ADDR, buf, length + 2);
if (status != CSL_SOK)
{
return status;
}
return CSL_SOK;
}
/*
* MR11 [3] = 0: 1 byte addressing for SPD5 Hub device memory.
* Covers first 128 bytes of memory.
* Only applicable to SPD5 Hub device.
*/
CSL_Status spd5hub_read_register(Uint16 register_index, Uint16 number_of_bytes, Uint16 *data)
{
CSL_Status status;
if (register_index > 0x7F)
{
return CSL_ESYS_INVPARAMS;
}
status = i2c_base_read(CSL_I2C_SPDHUB_ADDR, ®ister_index, 1, data, number_of_bytes);
if (status != CSL_SOK)
{
return status;
}
return CSL_SOK;
}
CSL_Status spd5hub_write_a_register(Uint16 register_index, Uint16 mask, Uint16 data)
{
if (register_index > 0x7F)
{
return CSL_ESYS_INVPARAMS;
}
if ((mask & 0x00FF) == 0x0000)
{
return CSL_SOK;
}
CSL_Status status;
Uint16 buf[2] = {0};
Uint16 value = 0;
if ((mask & 0x00FF) != 0x00FF)
{
status = spd5hub_read_register(register_index, 1, &value);
if (status != CSL_SOK)
{
return status;
}
}
buf[0] = register_index;
buf[1] = (value & ~mask) | (data & mask);
status = i2c_base_write(CSL_I2C_SPDHUB_ADDR, buf, 2);
if (status != CSL_SOK)
{
return status;
}
return CSL_SOK;
}
CSL_Status spd5hub_legacy_read_spd(Uint16 offset, Uint16 length, Uint16 *data)
{
CSL_Status status;
if (offset > 0x03FF)
{
return CSL_ESYS_INVPARAMS;
}
Uint16 page = offset / 128;
Uint16 start = offset % 128;
status = spd5hub_write_a_register(11, 0x0F, page);
if (status != CSL_SOK)
{
return status;
}
Uint16 buf[1];
buf[0] = start | 0x80;
status = i2c_base_read(CSL_I2C_SPDHUB_ADDR, buf, 1, data, length);
if (status != CSL_SOK)
{
return status;
}
return CSL_SOK;
}
CSL_Status spd5hub_legacy_write_spd(Uint16 offset, Uint16 length, Uint16 *data)
{
CSL_Status status;
if (offset > 0x03FF)
{
return CSL_ESYS_INVPARAMS;
}
Uint16 page = offset / 128;
Uint16 start = offset % 128;
status = spd5hub_write_a_register(11, 0x0F, page);
if (status != CSL_SOK)
{
return status;
}
Uint16 buf[64];
Uint16 i;
buf[0] = start | 0x80;
for (i = 0; i < length; i++)
{
buf[i + 1] = data[i];
}
status = i2c_base_write(CSL_I2C_SPDHUB_ADDR, buf, length + 1);
if (status != CSL_SOK)
{
return status;
}
return CSL_SOK;
}
CSL_Status spd5hub_set_write_protection(Uint16 block_mask, Uint16 value)
{
CSL_Status status;
Uint16 mask = block_mask & 0x00FF;
status = spd5hub_write_a_register(12, mask, value);
if (status != CSL_SOK)
{
return status;
}
mask = block_mask >> 8;
status = spd5hub_write_a_register(13, mask, value);
if (status != CSL_SOK)
{
return status;
}
return status;
}
CSL_Status spd5hub_get_write_protection(Uint16 *value)
{
CSL_Status status;
Uint16 buf[2];
status = spd5hub_read_register(12, 2, buf);
if (status != CSL_SOK)
{
return status;
}
*value = buf[0] | (buf[1] << 8);
return CSL_SOK;
}
CSL_Status spd5hub_get_temperature(Uint16 *temperature)
{
CSL_Status status;
Uint16 buf[2];
status = spd5hub_read_register(49, 2, buf);
if (status != CSL_SOK)
{
return status;
}
*temperature = buf[0] | (buf[1] << 8);
return CSL_SOK;
}
CSL_Status spd5hub_get_temperature_limit(Uint16 *high_limit, Uint16 *low_limit, Uint16 *critical_high_limit, Uint16 *critical_low_limit)
{
CSL_Status status;
Uint16 buf[8];
status = spd5hub_read_register(28, 8, buf);
if (status != CSL_SOK)
{
return status;
}
*high_limit = buf[0] | (buf[1] << 8);
*low_limit = buf[2] | (buf[3] << 8);
*critical_high_limit = buf[4] | (buf[5] << 8);
*critical_low_limit = buf[6] | (buf[7] << 8);
return CSL_SOK;
}
CSL_Status spd5hub_set_temperature_limit(Uint16 high_limit, Uint16 low_limit, Uint16 critical_high_limit, Uint16 critical_low_limit)
{
CSL_Status status;
Uint16 temp[4];
Uint16 reg;
Uint16 value;
Uint8 i;
// Memory Register: 28, 29.
temp[0] = high_limit;
// Memory Register: 30, 31.
temp[1] = low_limit;
// Memory Register: 32, 33.
temp[2] = critical_high_limit;
// Memory Register: 34, 35.
temp[3] = critical_low_limit;
reg = 28;
for (i = 0; i < 4; i++)
{
if (temp[i] != 0xFFFF)
{
temp[i] &= 0x1FFC;
value = temp[i] & 0x00FF;
status = spd5hub_write_a_register(reg++, 0xFF, value);
if (status != CSL_SOK)
{
return status;
}
value = temp[i] >> 8;
status = spd5hub_write_a_register(reg++, 0xFF, value);
if (status != CSL_SOK)
{
return status;
}
}
}
return CSL_SOK;
}
CSL_Status spd5hub_get_temperature_status(Uint16 *temp_status)
{
CSL_Status status;
Uint16 buf[1];
status = spd5hub_read_register(51, 1, buf);
if (status != CSL_SOK)
{
return status;
}
*temp_status = buf[0] & 0x0F;
return CSL_SOK;
}
CSL_Status spd5hub_clear_temperature_status(Uint16 clear_status)
{
CSL_Status status;
clear_status &= 0x000F;
status = spd5hub_write_a_register(19, 0xFF, clear_status);
return status;
}
void main(void)
{
CSL_Status status = 0;
Uint16 data[1024];
status = ts_i2c_init();
if (status != CSL_SOK)
return;
status = spd5hub_legacy_read_spd(0x000, 256, data);
if (status != CSL_SOK)
return;
status = spd5hub_legacy_read_spd(0x100, 256, data);
if (status != CSL_SOK)
return;
status = spd5hub_legacy_read_spd(0x200, 256, data);
if (status != CSL_SOK)
return;
status = spd5hub_legacy_read_spd(0x300, 256, data);
if (status != CSL_SOK)
return;
}
#include <stdio.h>
#include "csl_sysctrl.h"
#include "ts_i2c.h"
CSL_I2cObj i2cObj[CSL_I2C_PER_CNT];
pI2cHandle hI2c = NULL;
Uint16 timeout = CSL_I2C_MAX_TIMEOUT;
CSL_Status i2c_base_init(Uint16 channel)
{
volatile Uint16 looper;
switch (channel)
{
case CSL_I2C0:
hI2c = &i2cObj[CSL_I2C0];
hI2c->i2cRegs = CSL_I2C_0_REGS;
hI2c->sysCtrlRegs = CSL_SYSCTRL_REGS;
CSL_FINST(hI2c->sysCtrlRegs->PCGCR1, SYS_PCGCR1_I2CCG, ACTIVE);
CSL_FINS(hI2c->sysCtrlRegs->PSRCR, SYS_PSRCR_COUNT, CSL_I2C_RESET_COUNT_VAL);
CSL_FINST(hI2c->sysCtrlRegs->PRCR, SYS_PRCR_I2C_RST, RST);
for (looper = 0; looper < CSL_I2C_RESET_DELAY; looper++) {;}
break;
default:
return CSL_ESYS_INVPARAMS;
}
return CSL_SOK;
}
CSL_Status i2c_base_setup(CSL_I2cSetup *i2cSetup)
{
Uint16 pscValue;
Uint16 clock;
Uint16 d;
if (i2cSetup == NULL)
{
return CSL_ESYS_INVPARAMS;
}
// Set I2C address mode
CSL_FINS(hI2c->i2cRegs->ICMDR, I2C_ICMDR_XA, i2cSetup->addrMode);
// Set I2C Bit count value
CSL_FINS(hI2c->i2cRegs->ICMDR, I2C_ICMDR_BC, i2cSetup->bitCount);
// Enable/Disable loopback mode
CSL_FINS(hI2c->i2cRegs->ICMDR, I2C_ICMDR_DLB, i2cSetup->loopBack);
// Enable/Disable free running mode
CSL_FINS(hI2c->i2cRegs->ICMDR, I2C_ICMDR_FREE, i2cSetup->freeMode);
// Enable/Disable repeat mode
CSL_FINS(hI2c->i2cRegs->ICMDR, I2C_ICMDR_RM, i2cSetup->repeatMode);
// Set the I2C own address
CSL_FINS(hI2c->i2cRegs->ICOAR, I2C_ICOAR_OADDR, i2cSetup->ownAddr);
// calculating the IPSC value
pscValue = (i2cSetup->sysInputClk) / CSL_I2C_MODULE_CLOCK_FREQ;
// Adjust the Prescaler value
if (pscValue > (i2cSetup->sysInputClk % CSL_I2C_MODULE_CLOCK_FREQ))
{
pscValue -= CSL_I2C_PSC_ADJUST_VAL;
}
if (pscValue == CSL_I2C_PSC0)
{
d = CSL_I2C_PSC0_DVAL;
}
else if (pscValue == CSL_I2C_PSC1)
{
d = CSL_I2C_PSC1_DVAL;
}
else
{
d = CSL_I2C_PSC2TOFF_DVAL;
}
CSL_FINS(hI2c->i2cRegs->ICPSC, I2C_ICPSC_IPSC, pscValue);
// calculating the ICCLKL and ICCLKH register values
clock = (((i2cSetup->sysInputClk * CSL_I2C_CLK_MULT * CSL_I2C_CLK_MULT) / \
((pscValue + CSL_I2C_PSC_ADJUST_VAL) * i2cSetup->i2cBusFreq * \
CSL_I2C_CLK_MULT * 2u)) - (d));
// Configure clock low register
CSL_FINS(hI2c->i2cRegs->ICCLKL, I2C_ICCLKL_ICCL, clock);
// Configure clock high register
CSL_FINS(hI2c->i2cRegs->ICCLKH, I2C_ICCLKH_ICCH, clock);
// Bring the I2C out of reset
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_IRS, SET);
return CSL_SOK;
}
CSL_Status i2c_base_bus_reset()
{
CSL_I2cSetup i2cSetup;
CSL_Status status;
if (hI2c == NULL)
{
return CSL_ESYS_BADHANDLE;
}
CSL_FINST(hI2c->sysCtrlRegs->PCGCR1, SYS_PCGCR1_I2CCG, ACTIVE);
CSL_FINS(hI2c->sysCtrlRegs->PSRCR, SYS_PSRCR_COUNT, CSL_I2C_RESET_COUNT_VAL);
CSL_FINST(hI2c->sysCtrlRegs->PRCR, SYS_PRCR_I2C_RST, RST);
// Setup I2C module
i2cSetup.addrMode = CSL_I2C_ADDR_7BIT;
i2cSetup.bitCount = CSL_I2C_BC_8BITS;
i2cSetup.loopBack = CSL_I2C_LOOPBACK_DISABLE;
i2cSetup.freeMode = CSL_I2C_FREEMODE_DISABLE;
i2cSetup.repeatMode = CSL_I2C_REPEATMODE_DISABLE;
i2cSetup.ownAddr = CSL_I2C_OWN_ADDR;
i2cSetup.sysInputClk = CSL_I2C_SYS_CLK;
i2cSetup.i2cBusFreq = CSL_I2C_BUS_FREQ;
status = i2c_base_setup(&i2cSetup);
if (status != CSL_SOK)
{
printf("i2c_base_setup Failed!!\n");
return status;
}
return CSL_SOK;
}
CSL_Status i2c_base_send_stopbit()
{
if (hI2c == NULL)
{
return CSL_ESYS_BADHANDLE;
}
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_STP, SET);
return CSL_SOK;
}
CSL_Status i2c_base_smbus_quick(Uint16 slaveAddr)
{
volatile Uint16 looper;
Uint16 statusByte;
if (hI2c == NULL)
{
return CSL_ESYS_BADHANDLE;
}
for (looper = 0; looper < timeout; looper++)
{
statusByte = CSL_FEXT(hI2c->i2cRegs->ICSTR, I2C_ICSTR_BB);
if (statusByte == FALSE)
{
break;
}
}
if (looper >= timeout)
{
return CSL_I2C_BUS_BUSY_ERR;
}
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_TRX, SET);
CSL_FINS(hI2c->i2cRegs->ICCNT, I2C_ICCNT_ICDC, 0);
CSL_FINS(hI2c->i2cRegs->ICSAR, I2C_ICSAR_SADDR, slaveAddr);
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_MST, SET);
//CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_STP, SET);
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_STT, SET);
// Wait for ACK.
for (looper = 0; looper < timeout; looper++)
{
statusByte = CSL_FEXT(hI2c->i2cRegs->ICSTR, I2C_ICSTR_NACK);
if (statusByte == FALSE)
{
break;
}
}
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_STP, SET);
if (looper >= timeout)
{
return CSL_I2C_NACK_ERR;
}
return CSL_SOK;
}
CSL_Status i2c_base_write_protocol(Uint16 slaveAddr, Uint16 *dataBuf, Uint16 dataLength)
{
volatile Uint16 looper;
Uint16 dataCount;
Uint16 statusByte;
// Set the TX mode
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_TRX, SET);
CSL_FINS(hI2c->i2cRegs->ICCNT, I2C_ICCNT_ICDC, dataLength);
CSL_FINS(hI2c->i2cRegs->ICSAR, I2C_ICSAR_SADDR, slaveAddr);
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_MST, SET);
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_STT, SET);
for (dataCount = 0; dataCount < dataLength; dataCount++)
{
for (looper = 0; looper < timeout; looper++)
{
statusByte = CSL_FEXT(hI2c->i2cRegs->ICSTR, I2C_ICSTR_ICXRDY);
if (statusByte == TRUE)
{
break;
}
}
if (looper >= timeout)
{
return CSL_I2C_TIMEOUT_ERROR;
}
CSL_FINS(hI2c->i2cRegs->ICDXR, I2C_ICDXR_D, *dataBuf++);
for (looper = 0; looper < timeout; looper++)
{
statusByte = CSL_FEXT(hI2c->i2cRegs->ICSTR, I2C_ICSTR_NACK);
if (statusByte == FALSE)
{
break;
}
}
if (looper >= timeout)
{
return CSL_I2C_NACK_ERR;
}
}
//CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_STP, SET);
return CSL_SOK;
}
CSL_Status i2c_base_read_protocol(Uint16 slaveAddr, Uint16 *dataBuf, Uint16 dataLength)
{
volatile Uint16 looper;
Uint16 dataCount;
Uint16 statusByte;
// Set the RX mode
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_TRX, CLEAR);
CSL_FINS(hI2c->i2cRegs->ICCNT, I2C_ICCNT_ICDC, dataLength);
CSL_FINS(hI2c->i2cRegs->ICSAR, I2C_ICSAR_SADDR, slaveAddr);
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_MST, SET);
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_STT, SET);
for (dataCount = 0; dataCount < dataLength; dataCount++)
{
for (looper = 0; looper < timeout; looper++)
{
statusByte = CSL_FEXT(hI2c->i2cRegs->ICSTR, I2C_ICSTR_ICRRDY);
if (statusByte == TRUE)
{
break;
}
}
if (looper >= timeout)
{
return CSL_I2C_TIMEOUT_ERROR;
}
*dataBuf++ = CSL_FEXT(hI2c->i2cRegs->ICDRR, I2C_ICDRR_D);
statusByte = CSL_FEXT(hI2c->i2cRegs->ICSTR, I2C_ICSTR_RSFULL);
if (statusByte == TRUE)
{
return CSL_I2C_RECEIVE_OVERFLOW_ERR;
}
}
//CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_STP, SET);
return CSL_SOK;
}
CSL_Status i2c_base_write(Uint16 slaveAddr, Uint16 *i2cWrBuf, Uint16 wrDataLength)
{
volatile Uint16 looper;
Uint16 statusByte;
CSL_Status status;
if (hI2c == NULL)
{
return CSL_ESYS_BADHANDLE;
}
if ((i2cWrBuf == NULL) && (wrDataLength > 0))
{
return CSL_ESYS_INVPARAMS;
}
// check for bus busy.
for (looper = 0; looper < timeout; looper++)
{
statusByte = CSL_FEXT(hI2c->i2cRegs->ICSTR, I2C_ICSTR_BB);
if (statusByte == FALSE)
{
break;
}
}
if (looper >= timeout)
{
return CSL_I2C_BUS_BUSY_ERR;
}
status = i2c_base_write_protocol(slaveAddr, i2cWrBuf, wrDataLength);
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_STP, SET);
return status;
}
CSL_Status i2c_base_read(Uint16 slaveAddr, Uint16 *i2cWrBuf, Uint16 wrDataLength, Uint16 *i2cRdBuf, Uint16 rdDataLength)
{
volatile Uint16 looper;
Uint16 statusByte;
CSL_Status status;
if (hI2c == NULL)
{
return CSL_ESYS_BADHANDLE;
}
if ((i2cRdBuf == NULL) && (rdDataLength > 0))
{
return CSL_ESYS_INVPARAMS;
}
if ((i2cWrBuf == NULL) && (wrDataLength > 0))
{
return CSL_ESYS_INVPARAMS;
}
for (looper = 0; looper < timeout; looper++)
{
statusByte = CSL_FEXT(hI2c->i2cRegs->ICSTR, I2C_ICSTR_BB);
if (statusByte == FALSE)
{
break;
}
}
if (looper >= timeout)
{
return CSL_I2C_BUS_BUSY_ERR;
}
status = i2c_base_write_protocol(slaveAddr, i2cWrBuf, wrDataLength);
if (status != CSL_SOK)
{
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_STP, SET);
return status;
}
for (looper = 0; looper < timeout; looper++) {;}
status = i2c_base_read_protocol(slaveAddr, i2cRdBuf, rdDataLength);
CSL_FINST(hI2c->i2cRegs->ICMDR, I2C_ICMDR_STP, SET);
return status;
}
Hi Tony,
我找到放附件的方式了
再麻煩幫忙。謝謝