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.

MSPM0G3105: MSPM0 SDK I2C lib issue

Part Number: MSPM0G3105
Other Parts Discussed in Thread: TCA9539

One of our customers is using MSPM0 to communication with IO expander TCA9539 via I2C.

one operation is write-data-read-data with repeated START.  Here is the code:

uint8 I2c_CfgReadTransfer (uint32* Register, uint32 slave_address, uint8 RegisterAddress, uint8 *I2c_in_buffer, uint8 i2c_buff_length )

{

    T_I2C_MASTER_TRANSMIT_STATUS return_value = I2C_MASTER_ERR_BUFFER_OVERFLOW;

    uint8 ReceptionCounter;

    DL_I2C_enableControllerReadOnTXEmpty( ((I2C_Regs*)Register) );

 

    /* Fill FIFO with Tx Data. Complete Transfer is of 8 bytes, only 4 are

     * required for the GPIO Port Expanders */

    DL_I2C_fillControllerTXFIFO( ((I2C_Regs*)Register), &RegisterAddress, (uint16)C_I2C_REG_ADD_SIZE);

 

    if( (C_I2C_RX_MAX_PACKET_SIZE > i2c_buff_length) & (0U != i2c_buff_length) )

    {

       if ( C_I2C_MAX_7_BIT_ADD >= slave_address )

       {

           /* Wait for I2C to be Idle */

           while (!( DL_I2C_getControllerStatus( ((I2C_Regs*)Register)) & C_I2C_CONTROLER_IN_IDLE_MASK));

 

           /* This function sends Start + Stop automatically */

           DL_I2C_startControllerTransfer( ((I2C_Regs*)Register), slave_address, DL_I2C_CONTROLLER_DIRECTION_RX, (i2c_buff_length) );

               /* Receive all bytes from target */

   ........

}

The highlighted API calls are correct to start the required operation. However, it does not work, because the last API DL_I2C_startControllerTransfer() clear (overwrite) the RD_ON_TXEMPTY bit set by previous DL_I2C_enableControllerReadOnTXEmpty() call.

It is an issue on DL_I2C_startControllerTransfer API. 

  • Hi Ansong,

    I just tested this on my end and it appears to be working as expected.

    What version of the SDK are you using, and what traffic do you see generated on the bus when DL_I2C_startControllerTransfer is called? 

    DL_I2C_startControllerTransfer masks off the bits which are intended to be written, so it should not be overwriting RD_ON_TXEMPTY.

    Best Regards,
    Brandon Fisher

  • our SDK version mspm0_sdk_1_00_00_04

    Here is our source code:

    __STATIC_INLINE void DL_I2C_startControllerTransfer(I2C_Regs *i2c,
    uint32_t targetAddr, DL_I2C_CONTROLLER_DIRECTION direction,
    uint16_t length)
    {
    // Specify target address and read/write mode
    DL_Common_updateReg(&i2c->MASTER.MSA,
    ((targetAddr << I2C_MSA_SADDR_OFS) | (uint32_t) direction),
    (I2C_MSA_SADDR_MASK | I2C_MSA_DIR_MASK));

    // STOP bit is generated after burst length number of bytes transferred
    DL_Common_updateReg(&i2c->MASTER.MCTR,
    (((uint32_t) length << I2C_MCTR_MBLEN_OFS) | I2C_MCTR_BURSTRUN_ENABLE |
    I2C_MCTR_START_ENABLE | I2C_MCTR_STOP_ENABLE),
    (I2C_MCTR_MBLEN_MASK | I2C_MCTR_BURSTRUN_MASK | I2C_MCTR_START_MASK |
    I2C_MCTR_STOP_MASK));
    }

    Form the highlighted mask value, you can see it mask off the RD_ON_TXEMPTY bit.

  • Hi Ansong,

    I'd recommend updating to the latest version (https://www.ti.com/tool/MSPM0-SDK#downloads), version 1.20. That is the version of the SDK I am using where it seems to work properly. 

    The way DL_Common_updateReg works it uses the inverse of the MASK to preserve the old register values, and then write back the old register values alongside the new register values, to avoid changing anything. See below for source for this function. 

    /**
     * @brief   Writes value to specified register - retaining bits unaffected by mask.
     *
     * @param[in] reg     Pointer to the register overlay for the peripheral.
     * @param[in] val     Value to be written to the register.
     * @param[in] mask    Mask defines which bits will be altered.
     */
    __STATIC_INLINE void DL_Common_updateReg(
        volatile uint32_t *reg, uint32_t val, uint32_t mask)
    {
        uint32_t tmp;
    
        tmp  = *reg;
        tmp  = tmp & ~mask;
        *reg = tmp | (val & mask);
    }
    

    If that mask included I2C_MCTR_RD_ON_TXEMPTY_MASK, then I would expect it to blank that value inadvertently. 

    Do you have a logic analyzer or anything you can probe the I2C pins with? Are you seeing that RD_ON_TXEMPTY bit reset in the register view of CCS after the call to DL_I2C_startControllerTransfer?

    Best Regards,
    Brandon Fisher

  • Hi, Brandon,

    You are right that the RD_ON_TXEMPTY is not cleared after  DL_I2C_startControllerTransfer call. It turns out that the root cause is the wrong address value by customer in the call.

    The problem is resolved. Thanks for your help.