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.

MSP432P401R: I2C Stalling

Part Number: MSP432P401R
Other Parts Discussed in Thread: BQ24735, BQ4050

I have a MSP-EXP432P401R connected to a SMBus via eUSCI0_B to a BQ24735 and BQ4050. Expanding the I2C driver lib examples, I was able to get the microcontroller talking to both devices. However I'm experiencing an occasional issue where the I2C_masterSendSingleByte gets stuck into an infinite while loop [while (!(EUSCI_B_CMSIS(moduleInstance)->rIFG.r & UCTXIFG))] causing the microcontroller to stall.

Specifically I'm trying to Read the BQ4050 battery status and then the BQ4050 relative state of charge (although I've tried to reverse the calls with the same result). On the second read the slave address is written out (Acknowledged), and then a stop condition occurs instead of the requested register address being written.

Here is the read function:

uint8_t ReadU1(uint8_t address)
{
    uint8_t value = 0;

    MAP_I2C_setSlaveAddress(EUSCI_B0_BASE, 0x0B);

    // Set the address we want to read
    MAP_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
    MAP_I2C_masterSendSingleByte(EUSCI_B0_BASE, address);

    // Verify the completion of the previous message
    while (MAP_I2C_masterIsStopSent(EUSCI_B0_BASE));

    value = MAP_I2C_masterReceiveSingleByte(EUSCI_B0_BASE);

    return value;
}

On the scope you see

where you would expect to see

What could be causing the stop condition to occur earlier than expected?

  • Hello Aaron,

    According to the MSP432P401R Driver Lib User's guide, it says you should Init Master, set slave address, set mode, then Enable the module.  

    I wonder if you should disable the module before calling the setSlave and setMode APIs, then re-enable.  Can you try that? 

    Thanks,

    JD 

  • Trying the disable/enable the module around the slave address and setting the mode caused the issue to occur every time instead of occasionally. Looking at the driver library source code, the mode is set by the send/receive functions so I removed that call. Testing with that change I don't see any stalls in the communication. I still feel like something may be wrong, but the code is working.

    uint8_t ReadU1(uint8_t address)
    {
        uint8_t value = 0;
    
        MAP_I2C_setSlaveAddress(EUSCI_B0_BASE, 0x0B);
    
        // Set the address we want to read
        MAP_I2C_masterSendSingleByte(EUSCI_B0_BASE, address);
    
        // Verify the completion of the previous message
        while (MAP_I2C_masterIsStopSent(EUSCI_B0_BASE));
    
        value = MAP_I2C_masterReceiveSingleByte(EUSCI_B0_BASE);
    
        return value;
    }

    According to the tech manual (26.4.14) the I2C module doesn't need to be in reset to set the slave address, so setting the slave address after enabling should be ok.

    One other item that caught my attention is that the clock is being stretched when receiving the first byte, which according to my understanding shouldn't happen. Immediately after the slave acknowledges the address the first byte should be clocked in.

    Feels like all of that should be handled in hardware and is about the same duration on the two reads that I'm monitoring on the scope.

  • I suggest you call MAP_I2C_masterIsStopSent again after the call to MAP_I2C_masterReceiveSingleByte. ReceiveSingleByte doesn't wait for the Stop to complete.