Part Number:TMS320C5535
你好
我司使用TMS320C5535AZAY10發生錯誤
現象:機率性讀取DDR5 SPD時發生錯誤,從示波器上來看,發現當讀取錯誤發生時,中間有多插入Stop訊號(紅圈處),初步懷疑是此stop所造成。
fw code 如附件。
應用環境:SPD燒入治具
麻煩協助確認問題,或FW code部分建議修正。
謝謝
Eva Lai:
附上檔案 DDR5 FW
,
Tony Tang:
DDR5是什么意思?C5535不支持外接DDR的啊。
,
Eva Lai:
hi Tony,我們是用此controller的I2C功能,來跟DDR5 的SPD HUB進行溝通,波形圖為下I2C command後跑出的波形,主要是去讀SPD HUB內的值。當發生錯誤時,如圖所示,會多出一個stop的波形。而此stop並非我們下給controller的,附檔是我們編寫的FW,再請麻煩協助確認是否有問題?此問題為機率性發生,並非每每都會出現,是否IC有哪些狀況會跑進stop condition的觸發?
,
Tony Tang:
Eva Lai 说:附上檔案 DDR5 FW
上传的不是一个附件,是一个链接吧。这个我们下载不了。
,
Eva Lai:
ts_i2c.c
#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 modulei2cSetup.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; }ts_i2c.h6283.main.c
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; }ts_i2c_base.c
#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 modeCSL_FINS(hI2c->i2cRegs->ICMDR, I2C_ICMDR_XA, i2cSetup->addrMode);// Set I2C Bit count valueCSL_FINS(hI2c->i2cRegs->ICMDR, I2C_ICMDR_BC, i2cSetup->bitCount);// Enable/Disable loopback modeCSL_FINS(hI2c->i2cRegs->ICMDR, I2C_ICMDR_DLB, i2cSetup->loopBack);// Enable/Disable free running modeCSL_FINS(hI2c->i2cRegs->ICMDR, I2C_ICMDR_FREE, i2cSetup->freeMode);// Enable/Disable repeat modeCSL_FINS(hI2c->i2cRegs->ICMDR, I2C_ICMDR_RM, i2cSetup->repeatMode);// Set the I2C own addressCSL_FINS(hI2c->i2cRegs->ICOAR, I2C_ICOAR_OADDR, i2cSetup->ownAddr);// calculating the IPSC valuepscValue = (i2cSetup->sysInputClk) / CSL_I2C_MODULE_CLOCK_FREQ;// Adjust the Prescaler valueif (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 valuesclock = (((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 registerCSL_FINS(hI2c->i2cRegs->ICCLKL, I2C_ICCLKL_ICCL, clock);// Configure clock high registerCSL_FINS(hI2c->i2cRegs->ICCLKH, I2C_ICCLKH_ICCH, clock);// Bring the I2C out of resetCSL_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 modulei2cSetup.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 modeCSL_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 modeCSL_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,
我找到放附件的方式了
再麻煩幫忙。謝謝