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.

TMS320C5535: DDR5 SPD 讀取機率性發生錯誤

Part Number: TMS320C5535


你好

我司使用TMS320C5535AZAY10發生錯誤

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

麻煩協助確認問題,或FW code部分建議修正。

謝謝

  • DDR5是什么意思?C5535不支持外接DDR的啊。

  • hi Tony,

    我們是用此controller的I2C功能,來跟DDR5 的SPD HUB進行溝通,波形圖為下I2C command後跑出的波形,主要是去讀SPD HUB內的值。
    當發生錯誤時,如圖所示,會多出一個stop的波形。而此stop並非我們下給controller的,附檔是我們編寫的FW,再請麻煩協助確認是否有問題?
    此問題為機率性發生,並非每每都會出現,是否IC有哪些狀況會跑進stop condition的觸發?

  • 附上檔案 DDR5 FW

    上传的不是一个附件,是一个链接吧。这个我们下载不了。

  • #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, &register_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.h
    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,

    我找到放附件的方式了

    再麻煩幫忙。謝謝