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.

MSPM33C321A: I2C data transfer stuck waiting at TX Buffer Empty

Expert 4365 points

Part Number: MSPM33C321A

Hi team, 

I'm working with the LP-MSPM33C321A and was able to make the timer work but have a problem of sending data to an I2C sensor. The following code should send one byte register address and one byte data to the sensor, but it is always stuck waiting at the Tx Buffer Empty: DL_I2CC_isTXFIFOEmpty(I2C_INST);

 

What may be causing this to stick here? Do I need to configure the FIFO size/threshold before use? I am using the example which has 64-byte FIFO size (maybe too big for 2-byte data transfer?)

 

The I2C bus is pulled to 3.3 Volts with 10K resister and I can measure the voltage is correct on the bus. 

 

void Sensor_write_reg(uint8_t reg, uint8_t data)

{

    transmitData[0] = reg;  // Reg address

    transmitData[1] = data;  // Data to the Reg

 

    /*

     * Fill FIFO with data.

     */

    Size = DL_I2CC_fillTXFIFO(I2C_INST, &transmitData[0], CommandSize);

 

    // Start transfer

    DL_I2CC_startTransfer(I2C_INST,I2C_TARGET_ADDRESS,DL_I2CC_DIRECTION_TX, CommandSize);

 

    // Wait for TX FIFO ready     but the code waits here forever.......... 

     while (DL_I2CC_isTXFIFOEmpty(I2C_INST) == 0 && DL_I2CC_getStatus(I2C_INST) != DL_I2CC_STATUS_ERROR) {

     };

 

     /* Wait for I2C to be Idle */

    while (!(DL_I2CC_getStatus(I2C_INST) & DL_I2CC_STATUS_IDLE))

        ;

     /* Add delay between transfers */

    delay_cycles(1000);

 

}

 

Best,
Luke

  •   while (DL_I2CC_isTXFIFOEmpty(I2C_INST) == 0 && DL_I2CC_getStatus(I2C_INST) != DL_I2CC_STATUS_ERROR) {

    getStatus() returns all of SR, and STATUS_ERROR is just one of the bits in it (UNICOMMI2CC_SR_ERR_MASK). Try instead:

      while (DL_I2CC_isTXFIFOEmpty(I2C_INST) == 0 && (DL_I2CC_getStatus(I2C_INST) & DL_I2CC_STATUS_ERROR) == 0) {

    Supposing that is what you encountered, I suspect you got a NACK from the target device, which is a different problem.

  • Hi Bruce, 

    Thanks for the response! When I only check if the FIFO is empty, I got stuck there since the FIFO never gets empty with the following code:

    while (DL_I2CC_isTXFIFOEmpty(I2C_INST) == 0);

    Without even checking any errors.

    Best,

    Luke

  • If you get a NACK, the TX FIFO won't empty -- you have to recognize the event and empty it yourself. [Ref TRM (SLAU962) Sec 23.2.3.4 (final paragraph)]. With the change I suggested, you'll at least be able to tell what's happening.

    Supposing that you are getting a NACK: (1) check the I2C address (2) check that the device (Vcc) is powered (3) check your wiring (4) if you have a scope, this might be a good time to dig it out.

  • Hey Bruce,

    I changed the code to your recommendation: while (DL_I2CC_isTXFIFOEmpty(I2C_INST) == 0 && (DL_I2CC_getStatus(I2C_INST) & DL_I2CC_STATUS_ERROR) == 0) {

    And now I can pass the I2C writing and the scope shown the clock and data on the bus. Unfortunately the sensor still does not work (turned on) after I followed the old working code. We have made the change on the hardware to accommodating 3,3V bus rather than the old 5V bus too. 

    Very strange it worked for a while and after reprogramming the board it no longer sends out the clock and data anymore.

    Best,

    Luke

  • If it's the Target which is (for whatever reason) hanging the bus, then resetting or reprogramming the Controller side won't necessarily clear it. You should probably power-cycle the Target side as well.

    Can you tell us what the Target is? 

    Also, what is the value of CommandSize? If it's >8, you probably need to have some more code to re-fill the TX FIFO.

  • I did recycle the power on both sides and it did not solve the problem. The sensor (target side) is a self mode sensor using MAX86916.

    I am very curious why the transmission worked (at least I can see the Clock and Data line activities and able to see the buffer emptied for a long time and then suddenly stopped). The value of CommandSize is only set to 2... here is the current code. I don't see the clock or data on the bus anymore.

    /* I2C Target address */

    #define I2C_TARGET_ADDRESS (0x57)

    #define CommandSize 2

    uint8_t gTxCount = 0;

    int Timer0IsInt = 0, NumOfTimerInt = 0, Alt = 0;

    int Count = 0, Size = 0;;

     

    uint8_t transmitData[2] ={};

     

    void Sensor_write_reg(uint8_t reg, uint8_t data, uint8_t uch_sensor)

    {

        transmitData[0] = reg;  // Reg address

        transmitData[1] = data;  // Data to the Reg

       

        if(uch_sensor == I2C0)

        {

     

            //Fill FIFO with data.

            Size = DL_I2CC_fillTXFIFO(I2C_INST, &transmitData[0], CommandSize);

     

            // Start transfer

            DL_I2CC_startTransfer(I2C_INST,I2C_TARGET_ADDRESS,DL_I2CC_DIRECTION_TX, CommandSize);

     

            // Wait for TX FIFO ready

            while(DL_I2CC_isTXFIFOEmpty(I2C_INST) == 0&&(DL_I2CC_getStatus(I2C_INST)&DL_I2CC_STATUS_ERROR) == 0) ;

     

            /* Wait for I2C to be Idle */

            while (!(DL_I2CC_getStatus(I2C_INST) & DL_I2CC_STATUS_IDLE));

     

        } else //The other sensor

        {

            //Fill FIFO with data.

     

            Size = DL_I2CC_fillTXFIFO(I2C_0_INST, &transmitData[0], CommandSize);

     

            // Start transfer

            DL_I2CC_startTransfer(I2C_0_INST,I2C_TARGET_ADDRESS,DL_I2CC_DIRECTION_TX, CommandSize);

     

            // Wait for TX FIFO ready

            while(DL_I2CC_isTXFIFOEmpty(I2C_0_INST) == 0 && (DL_I2CC_getStatus(I2C_INST) & DL_I2CC_STATUS_ERROR) == 0) ;

       

            /* Wait for I2C to be Idle */

            while (!(DL_I2CC_getStatus(I2C_0_INST) & DL_I2CC_STATUS_IDLE));

        }    

        /* Add delay between transfers */

        delay_cycles(1000);

    }

    Best,

    Luke

  • At the time the transactions stop: (1) what is the state of the [SDA/SCL] pins? (2) if you pause your program, where is it executing?

    I tried 2 experiments:

    a) I hacked a copy of i2c_controller_rw_multibyte_poll to call this function repeatedly for 5 minutes or so. I expected NACKs, which I got, but it didn't hang.

    b) I changed the program from (a) to talk to an Adafruit MPR121 breakout board (address 0x5A), writing 0xAA to register 0x5B [debounce] repeatedly for about 5 minutes. All the transactions are successful, and I haven't seen any hangs.

    I'm wondering if something is going on outside the code you posted.

    [Edit: Also, please use Insert->Code; this makes it much easier to read and to copy/paste.]

    [Edit: Minor clarification.]

  • Hi Bruce, 

    Are you able to share the working test code you have so I can take a look and compare to what's going wrong in our code?

    Best,

    Luke

  • Here's what I was working with. It only uses one I2C, on PA10/11 (since the PA0/1 pullups aren't installed on my Launchpad).

    x-i2c_controller_rw_multibyte_fifo_poll_LP_MSPM33C321A.zip