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.

LAUNCHXL-F28379D: Problems with i2c_ex1_loopback Example Code

Part Number: LAUNCHXL-F28379D
Other Parts Discussed in Thread: TMS320F28379D

Hi All,

The i2c_ex1_loopback example loads and runs as expected, but I'm having a hard time understanding what's going on inside the code.

I've disabled loopback mode and inserted some I2C commands and data to populate a simple 2x16 char display.

Using the ISR to send data works until I issue a stop condition.  As long as I don't use a stop condition (using the existing function "I2C_sendStopCondition(I2CA_BASE);"), all data is received by the display and all is well.

However, if I insert a stop condition, none of the code following it will stream over the I2C bus.

Here's the code without a stop condition until after all data has been sent: (display responds appropriately)

        strcpy(Line1, "  GMS-504DZ II  ");
                    // 1234567890123456
        strcpy(Line2, " FW Ver. 0.00.3 ");
                    // 1234567890123456

    I2C_setDataCount(I2CA_BASE, 2);         // Set number of bytes to transmit in the following I2C packets

        // Turn display on
    I2C_putData(I2CA_BASE, 0xfe);           // BYTE 1: Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x41);       // BYTE 2: 0x41 is the command to turn on the display
        I2C_sendStartCondition(I2CA_BASE);  // Start sending the packet
//        I2C_sendStopCondition(I2CA_BASE);
        DEVICE_DELAY_US(125);               // Wait time specified by display manufacturer


        // Setup display to write 1st line
        I2C_putData(I2CA_BASE, 0xfe);           // BYTE 1: Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x51);       // BYTE 2: 0x51 is the command to 'clear screen'
        I2C_sendStartCondition(I2CA_BASE);  // Start sending the packet
        DEVICE_DELAY_US(900);               // Wait time specified by display manufacturer

        I2C_putData(I2CA_BASE, 0xfe);           // Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x4c);       // 0x4c is the command to turn the 'blinking cursor off'
        I2C_sendStartCondition(I2CA_BASE);  // Send the command message stated immediately above
        DEVICE_DELAY_US(125);               // Wait time specified by display manufacturer

        I2C_putData(I2CA_BASE, 0xfe);           // Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x46);       // 0x46 is the command to send 'cursor home'
        I2C_sendStartCondition(I2CA_BASE);  // Start sending the packet
        DEVICE_DELAY_US(900);               // Wait time specified by display manufacturer

        I2C_setDataCount(I2CA_BASE, 3);         // Set number of bytes to transmit in the following I2C packets

        I2C_putData(I2CA_BASE, 0xfe);           // Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x45);       // 0x45 is the command to 'set cursor'
        I2C_putData(I2CA_BASE, 0x00);       // 0x00 sets the cursor to 'Line 1, position 1'
        I2C_sendStartCondition(I2CA_BASE);  // Start sending the packet
        DEVICE_DELAY_US(125);               // Wait time specified by display manufacturer

        I2C_setDataCount(I2CA_BASE, 1);         // Set number of bytes to transmit in the following I2C packets

        // Send 1st line characters
        for(i = 0; i < 16; i++) {
            I2C_putData(I2CA_BASE, (uint16_t)Line1[i]);   // Send character to display
            I2C_sendStartCondition(I2CA_BASE);  // Send the character stated immediately above
            DEVICE_DELAY_US(100);               // Wait time specified by display manufacturer
        }

        I2C_setDataCount(I2CA_BASE, 3);         // Set number of bytes to transmit in the following I2C packets

        I2C_putData(I2CA_BASE, 0xfe);           // Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x45);       // 0x45 is the command to 'set cursor'
        I2C_putData(I2CA_BASE, 0x40);       // 0x00 sets the cursor to 'Line 2, position 1'
        I2C_sendStartCondition(I2CA_BASE);  // Start sending the packet
        DEVICE_DELAY_US(125);               // Wait time specified by display manufacturer

        I2C_setDataCount(I2CA_BASE, 1);         // Set number of bytes to transmit in the following I2C packets

        // Send 2nd line characters
        for(i = 0; i < 16; i++) {
            I2C_putData(I2CA_BASE, Line2[i]);   // Send character to display
            I2C_sendStartCondition(I2CA_BASE);  // Send the character stated immediately above
            DEVICE_DELAY_US(100);               // Wait time specified by display manufacturer
        }

        I2C_sendStopCondition(I2CA_BASE);

        //
        // Clear interrupt flag
        //
        I2C_clearInterruptStatus(I2CA_BASE, I2C_INT_TXFF);
    }

    //
    // Issue ACK
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);

Here's what the above code produces:  (all commands and data appear as expected and 2x16 display shows message correctly)

Here's the code with one instance of a stop condition after the first packet has been sent: (same as above, but stop condition function uncommented)

        strcpy(Line1, "  GMS-504DZ II  ");
                    // 1234567890123456
        strcpy(Line2, " FW Ver. 0.00.3 ");
                    // 1234567890123456

    I2C_setDataCount(I2CA_BASE, 2);         // Set number of bytes to transmit in the following I2C packets

        // Turn display on
    I2C_putData(I2CA_BASE, 0xfe);           // BYTE 1: Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x41);       // BYTE 2: 0x41 is the command to turn on the display
        I2C_sendStartCondition(I2CA_BASE);  // Start sending the packet
        I2C_sendStopCondition(I2CA_BASE);
        DEVICE_DELAY_US(125);               // Wait time specified by display manufacturer


        // Setup display to write 1st line
        I2C_putData(I2CA_BASE, 0xfe);           // BYTE 1: Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x51);       // BYTE 2: 0x51 is the command to 'clear screen'
        I2C_sendStartCondition(I2CA_BASE);  // Start sending the packet
        DEVICE_DELAY_US(900);               // Wait time specified by display manufacturer

        I2C_putData(I2CA_BASE, 0xfe);           // Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x4c);       // 0x4c is the command to turn the 'blinking cursor off'
        I2C_sendStartCondition(I2CA_BASE);  // Send the command message stated immediately above
        DEVICE_DELAY_US(125);               // Wait time specified by display manufacturer

        I2C_putData(I2CA_BASE, 0xfe);           // Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x46);       // 0x46 is the command to send 'cursor home'
        I2C_sendStartCondition(I2CA_BASE);  // Start sending the packet
        DEVICE_DELAY_US(900);               // Wait time specified by display manufacturer

        I2C_setDataCount(I2CA_BASE, 3);         // Set number of bytes to transmit in the following I2C packets

        I2C_putData(I2CA_BASE, 0xfe);           // Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x45);       // 0x45 is the command to 'set cursor'
        I2C_putData(I2CA_BASE, 0x00);       // 0x00 sets the cursor to 'Line 1, position 1'
        I2C_sendStartCondition(I2CA_BASE);  // Start sending the packet
        DEVICE_DELAY_US(125);               // Wait time specified by display manufacturer

        I2C_setDataCount(I2CA_BASE, 1);         // Set number of bytes to transmit in the following I2C packets

        // Send 1st line characters
        for(i = 0; i < 16; i++) {
            I2C_putData(I2CA_BASE, (uint16_t)Line1[i]);   // Send character to display
            I2C_sendStartCondition(I2CA_BASE);  // Send the character stated immediately above
            DEVICE_DELAY_US(100);               // Wait time specified by display manufacturer
        }

        I2C_setDataCount(I2CA_BASE, 3);         // Set number of bytes to transmit in the following I2C packets

        I2C_putData(I2CA_BASE, 0xfe);           // Notify the I2C bus that a command is coming
        I2C_putData(I2CA_BASE, 0x45);       // 0x45 is the command to 'set cursor'
        I2C_putData(I2CA_BASE, 0x40);       // 0x00 sets the cursor to 'Line 2, position 1'
        I2C_sendStartCondition(I2CA_BASE);  // Start sending the packet
        DEVICE_DELAY_US(125);               // Wait time specified by display manufacturer

        I2C_setDataCount(I2CA_BASE, 1);         // Set number of bytes to transmit in the following I2C packets

        // Send 2nd line characters
        for(i = 0; i < 16; i++) {
            I2C_putData(I2CA_BASE, Line2[i]);   // Send character to display
            I2C_sendStartCondition(I2CA_BASE);  // Send the character stated immediately above
            DEVICE_DELAY_US(100);               // Wait time specified by display manufacturer
        }

        I2C_sendStopCondition(I2CA_BASE);

        //
        // Clear interrupt flag
        //
        I2C_clearInterruptStatus(I2CA_BASE, I2C_INT_TXFF);
    }

    //
    // Issue ACK
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);

Here's what happens with a stop condition: (no data is sent over I2C bus after the stop)

If I look at the registers just before the start condition function is called, after the stop condition was previously called, the registers look like this:

The MST register is '0', so I suspect nothing else will be sent until it's back in master mode.  But, why did MST change to '0'?  What am I missing?  Do I need to reconfigure the I2C registers after every stop condition?

I've read the TMS320F28379D documentation (spruhm8i.pdf) several times, but I don't see what I'm doing wrong.

Any help is greatly appreciated.

Thanks,

robin

  • The technical reference manual description of MST does say that MST is automatically changed from 1 to 0 when the I2C master generates the STOP condition, so it sounds like that's the expected behavior. Does setting the MST bit again before trying your next transmission solve the issue?

    Whitney

  • Hi Whitney,

    Thanks for the reply.

    Yes, when resetting to master mode, I2C data will again transmit.

    I'd like to send I2C data to the display, then send the stop condition, then return to the main loop. In the main loop, things happen that change what the display should be displaying.  Once the array containing data for the display has been updated, I can't see how to initiate the fifo interrupt again.

    If no stop condition has occurred, then the processor spends all of its time in the I2C interrupt routine.  There's no time for the main loop to do anything.

    The problem I can't quite figure out now, is how to initiate a fifo interrupt after a stop condition has occurred.  TXFFINT is read only. 

    TXFFST sets the threshold for comparison to TXFFIL (and will set TXFFINT when it drops below the value in TXFFIL), but TXFFST is read only, and it's set to 0x10.  How does TXFFST receive its value?  What is to the procedure to determine the value to set TXFFIL to?  My packets vary in byte length from 1 to as much as 16, so should I change TXFFIL each time the packet size changes?

    Is there any documentation that provides more detailed information about the interaction between the I2C registers?

    Thanks for your valuable help.

  • TXFFST tells you how many words are currently in the FIFO, so as you write to I2CDXR it will increase and as the data is sent it should decrease. You also need to keep an eye on the level when you're writing data to the buffer to make sure that you don't overflow it (it can only fit 16 words).

    You have a lot of delays in the code you shared above which should give the FIFO time to empty out, but it wouldn't hurt to check TXFFST to be sure there's room for the next chunk of data you want to send.

    The device technical reference manual really is going to be the best resource for information about the registers. There's also this wiki page with some tips although it mostly describes specific scenarios like NACK handling and master receiver mode.

    processors.wiki.ti.com/.../I2C_Tips

    Whitney