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.

MSP430FR2355: Issue with Driverlib I2C masterSendMultiByteStart

Part Number: MSP430FR2355
Other Parts Discussed in Thread: TMP102

Hi,

I'm using the MSP430 to communicate with some temperature devices through I2C. I'm using the driverlib library and I experienced an odd behavior of the I2C channel when using this library.

When trying to repeatedly send multiple byte message, the first byte of the message is not sent.. here is a code example:

 

void I2C_EUSCI_B1_Config()

{

                Param.selectClockSource = EUSCI_I2C_CLOCKSOURCE_SMCLK;

                Param.i2cClk = CS_getSMCLK();

                Param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_100KBPS;

                Param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;

               

                EUSCI_B_I2C_initMaster(EUSCI_B1_BASE,&param);

                EUSCI_B_I2C_enable(EUSCI_B1_BASE);

}

 

Void main()

{

                While(1)

                {

                // I2C Tx message – 0x01, 0xAA

                EUSCI_B_I2C_setSlaveAddress(EUSCI_B1_BASE, TMP102_ADDRESS);

                EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, 0x01);

                EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B1_BASE, 0xAA);

                EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B1_BASE);

               

                // I2C Tx message – 0x01, 0xBA

                EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, 0x01);

                EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B1_BASE, 0xBA);

                EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B1_BASE);

                }

}

The first time it enters the while loop, the first message is sent correctly - 0x01 and then 0xAA. But in the next messages the 0x01 is not sent again.

In all messages only the 0xAA and 0xBA are sent.

I saw another strange behavior, after sending the first message (0x01, 0xAA) and then trying to send single byte message, no data byte is sent... only the address. 

Seems like, for some reason, it discards the first byte of the transmission.

Would appreciate you help,

Thank you!

  • I haven't seen this particular symptom, but I suspect it has to do with requesting the Stop very early, then doing a (repeated) Start before the Stop is issued. I think this could result in a "phantom" TXIFG which loses the next byte.

     EUSCI_B_I2C_masterSendMultiByteFinish handles this sequence, so the Stop is requested after the final byte is written. For your two-byte transaction, try replacing the call to SendMultiByteNext with a call to SendMultiByteFinish, and removing the call to MultiByteStop.

  • Hi Bruce, 

    thank you for you reply!

    I tried doing exactly as you suggested but it doesn’t solve the problem..

  • Try adding this line just after each call to SendMultiByteStop:

    >  while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B1_BASE)); // Wait for Stop completion

    The Stop function requests a Stop (UCTXSTP) but doesn't wait for it to be issued, so this pauses until it's done. Since this is a kind of a write-behind thing, you could alternatively do this Before any call to Start, which lets you do other things in the meantime (roughly 2 byte-times).

    As I mentioned, this isn't the "usual" symptom for requesting a Start while a Stop is pending, but when I added that code the symptom vanished.

  • I tried adding this line and it did not solve the problem.. Still the first message is ok but all the following messages are sent without the first byte (0x01 is not sent).

  • When I added this line (two places) the symptom disappeared.

    I was using an LIS3DH, since I don't have a TMP102.

    Other than that I'm not sure what we're doing differently.

  • I noticed that after the first time 0x01, 0xF0 message is sent correctly, if I try to send a single byte message, the value in this message is always 0xFF no matter what value I write in the code...

  • I'm running out of ways to replicate your setup. Can you describe your platform? How do you tell that the byte is missing? (I used a Launchpad, an Adafruit breakout board, and a scope.)

    Is there other code you haven't posted? In particular: You should not be enabling any of the I2C interrupts.

    I suppose the next step would be to go back to basics. TI publishes an eUSCI troubleshooting document here:

    https://www.ti.com/lit/an/slaa734a/slaa734a.pdf

    You might try one (or more) of the TI examples, maybe starting with eusci_b_i2c_ex3_masterTxMultiple (you'll have to customize it):

    https://dev.ti.com/tirex/explore/node?node=A__AGgUyb0qJAc26U45ojcLdw__msp430ware__IOGqZri__LATEST

  • The msp430 is mounted on a custom board and I'm using a scope to debug it. Using the scope I can see that the byte is missing.

    There is no other code that I haven't posted... 

    I noticed that the program gets stuck on the "wait for Stop completion" loop:
    while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B1_BASE)); // Wait for Stop completion

    Looking at the EUSCI_B1 registers I see this:

    UCB1STATW register:
    UCSCLLOW = '1'
    UCBBUSY = '1'

    UCB1CTLW0 register:
    UCTXSTT = '1'
    UCTXSTP = '1'

    It doesn't get stuck on the first iteration but after running for some time.

  • This is a bit of an odd symptom. As far as I know you can't escape SendMultiByteNext with STT=1, and you can't escape that spin loop with STP=1, so I don't know how they can both be set (avoiding that is kind of the goal of this exercise).

    One (usually quick) diagnostic experiment is to slow the bus way down, which often alters the symptom -- sometimes it gets better, sometimes worse, but either way is a clue. SET_DATA_RATE_100KBPS is just the number 100000, so you can put some other number there.

    Is your "param" variable in global storage (i.e. 0-initialized at startup)?

    [Edit: minor clarification.]

  • I just ran my setup (without interruption) for over a half-hour with no hangups. I suppose there could be a difference in how the respective slaves are behaving, but the TMP102 in particular claims it never drives SCL, so I don't know how it would influence the Master.

    Anyway, for clarity here's what I've been working with:

    #include "driverlib.h"
    #define HZ          1000000UL   // 1MHz since we don't change it
    #define USE_I2CS    0           // Didn't replicate
    #define USE_FINISH  0           // Didn't fix
    #define WAIT_FOR_STOP 1         // Seems to work
    #if USE_I2CS
    #include "i2cs.h"               // Loopback slave on UCB0
    #define TMP102_ADDRESS  I2CS_ADDR
    #define REG_ADDR        0x01    // From the original
    #else
    #define TMP102_ADDRESS  0x18    // LIS3DH
    #define REG_ADDR        0x08    // Don't try to write reg 1
    #endif
    EUSCI_B_I2C_initMasterParam Param;
    void I2C_EUSCI_B1_Config()
    {
        P4OUT  |= (BIT6|BIT7);
        P4REN  |= (BIT6|BIT7);      // Enable pullups
        P4SEL0 |= (BIT6|BIT7);      // P4.6/7 as UCB1SDA/SCL per ds Table 6-66
        Param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK; // EUSCI_I2C_CLOCKSOURCE_SMCLK;
        Param.i2cClk = CS_getSMCLK();
        Param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_100KBPS;
        Param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
        EUSCI_B_I2C_initMaster(EUSCI_B1_BASE, &Param);
        EUSCI_B_I2C_enable(EUSCI_B1_BASE);
    }
    
    void main()
    {
        WDT_A_hold(WDT_A_BASE);
        PM5CTL0 &= ~LOCKLPM5;
        I2C_EUSCI_B1_Config();
    #if USE_I2CS
        i2cs_init();
    #endif // USE_I2CS
        __enable_interrupt();
        while(1)
        {
            // I2C Tx message – 0x01, 0xAA
            EUSCI_B_I2C_setSlaveAddress(EUSCI_B1_BASE, TMP102_ADDRESS);
            EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, REG_ADDR);
    #if USE_FINISH
            EUSCI_B_I2C_masterSendMultiByteFinish(EUSCI_B1_BASE, 0xAA);
    #else
            EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B1_BASE, 0xAA);
            EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B1_BASE);
    #endif // USE_FINISH
    #if WAIT_FOR_STOP
            while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B1_BASE));
    #endif // WAIT_FOR_STOP
    
            // I2C Tx message – 0x01, 0xBA
            EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, REG_ADDR);
    #if USE_FINISH
            EUSCI_B_I2C_masterSendMultiByteFinish(EUSCI_B1_BASE, 0xBA);
    #else
            EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B1_BASE, 0xBA);
            EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B1_BASE);
    #endif // USE_FINISH
    #if WAIT_FOR_STOP
            while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B1_BASE));
    #endif // WAIT_FOR_STOP
    
           // __delay_cycles(HZ/2);       // Pause to read the scope
        }
    }
    

**Attention** This is a public forum