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.

I2C on TM4C129

Other Parts Discussed in Thread: ENERGIA, TM4C1294NCPDT

I've been trying, with no success, to use a code for i2c that worked in stellaris and tm4c123 launchpad in the new tm4c129 launchpad. I just changed the pin ports configs

i've been searching and it seems that the i2c fuctions in TivaWare are now diferent for the tm4c129. Is there any documentation highlighting this diferences somewhere for better reading?

My code is the folowing for setup

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

GPIOPinConfigure(GPIO_PB2_I2C0SCL);
GPIOPinConfigure(GPIO_PB3_I2C0SDA);

GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

I2CMasterInitExpClk(I2C0_BASE, F_CPU, ulI2CSpeed);

and i have this fuction for sending:

while(I2CMasterBusy(ulI2CBase)) {}

//
// Tell the master module what address it will place on the bus when
// writing to the slave.
//
I2CMasterSlaveAddrSet(ulI2CBase, ucSlaveAdress, 0);

//
// Place the command to be sent in the data register.
//
I2CMasterDataPut(ulI2CBase, ucReg);

//
// Initiate send of data from the master.
//
I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_SEND_START);

//
// Wait until master module is done transferring.
//

while(I2CMasterBusy(ulI2CBase)) {}

//
// Check for errors.
//
if( I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
{
return 0;
}

//
// Place the value to be sent in the data register.
//
I2CMasterDataPut(ulI2CBase, ucValue);

//
// Initiate send of data from the master.
//
I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_SEND_CONT);

//
// Wait until master module is done transferring.
//

while(I2CMasterBusy(ulI2CBase)) {}

//
// Check for errors.
//
if( I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
{
return 0;
}

//
// Initiate send of data from the master.
//
I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_SEND_FINISH);

//
// Wait until master module is done transferring.
//

while(I2CMasterBusy(ulI2CBase)) {}

//
// Check for errors.
//
if( I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
{
return 0;
}

//
// Return 1 if there is no error.
//
return 1;

  • Hello Luois

    When migrating a code from TM4C123 to TM4C129 there are some careabouts that are required.

    Did you go through the following document

    http://www.ti.com/lit/pdf/spma065

    The code you have posted is "definitely" not the full code, so it is very important that you first ensure that the document is adhered to.

    Secondly, the LaunchPad for TM4C129 does not have Pull Up on PB2 and PB3 pins. So do make sure that there is an external pull up.

    Regards

    Amit

  • I actualy read that document. It just states additions from the tm4c123 and no loss of features or available fuctions. This is what realy confuses me

    This is actualy the full code for setup and sending 1 register. This is from a user made API for stelaris.

  • Hello Luois,

    Yes, that is correct that there is no loss of feature for I2C. But the manner in which System Clock is used (it is one of the parameters for the I2C Master Configuration). That is why I have requested for the full code (send it as an attachment).

    Also the other point was about the Pull Up Resistance. Is it there on the board?

    Regards

    Amit

  • About the pull-up, i have 1 in sda and in scl in a breadboard yes. 

    The code let me make it more readable 

    About the systemclock, i'm using energia so i use F_CPU wich is a macro for the set frequency wich is usualy used to work with this kind of things

  • Hello Luois,

    Thanks for the info on Pull Up. Is it possible to send a scope snapshot?

    Also when you run the above code, does it get stuck in some while loop? This kind of information would be useful.

    Regards

    Amit

  • scope snapshot? sorry i don't know what that is :x arduino coding kinda made me dumb

    the code never gets stuck, i actualy tried turning on a led inside the loop and off outside, and also doing some UART debuging after not seing the led even turning on.

  • ok so a bit more insigth.

    I'm using this with a SRF08 sonar sensor. I'm just sending "start ranging" command wich should be shown by a blinking led on the SRF08. That's not hapening.

    Here is the code i'm using for that, i hope it's readable

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <inttypes.h>
    #include "wiring_private.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_i2c.h"
    #include "driverlib/gpio.h"
    #include "driverlib/debug.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/i2c.h"
    #include "I2C_Stellaris_API.h"
    
    void setup()
    {
      // put your setup code here, to run once:
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
    
      GPIOPinConfigure(GPIO_PB2_I2C0SCL);
      GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    
      GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);	
      GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
    
    
      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    
    
      I2CMasterInitExpClk(I2C0_BASE, F_CPU, false);  
    }
    
    void loop()
    {
      
    SendReg();
    delay(100);
    }
    
    int SendReg(){
    
    	//
    	// Wait until master module is done transferring.
    	//
    
    while(I2CMasterBusy(I2C0_BASE)) {}
    	
    
        //
        // Tell the master module what address it will place on the bus when
        // writing to the slave.
        //
         I2CMasterSlaveAddrSet(I2C0_BASE, 0x71, 0);
    
        //
        // Place the command to be sent in the data register.
        //
         I2CMasterDataPut(I2C0_BASE, 0x00);
    
        //
        // Initiate send of data from the master.
        //
         I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
    
        //
        // Wait until master module is done transferring.
        //
    
    while(I2CMasterBusy(I2C0_BASE)) {}
    
        //
        // Check for errors.
        //
        if( I2CMasterErr(I2C0_BASE) != I2C_MASTER_ERR_NONE)
        {
            return 0;
        }
    
        //
        // Place the value to be sent in the data register.
        //
         I2CMasterDataPut(I2C0_BASE, 0x51);
    
        //
        // Initiate send of data from the master.
        //
         I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
    
        //
        // Wait until master module is done transferring.
        //
    
    while(I2CMasterBusy(I2C0_BASE)) {}
    
        //
        // Check for errors.
        //
        if( I2CMasterErr(I2C0_BASE) != I2C_MASTER_ERR_NONE)
        {
            return 0;
        }
    
        //
        // Initiate send of data from the master.
        //
         I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    
        //
        // Wait until master module is done transferring.
        //
    
    while(I2CMasterBusy(I2C0_BASE)) {}
    
        //
        // Check for errors.
        //
        if( I2CMasterErr(I2C0_BASE) != I2C_MASTER_ERR_NONE)
        {
            return 0;
        }
    
        //
        // Return 1 if there is no error.
        //
        return 1;
    }

  • Hello Luois,

    I am not familiar with Energia either. So I will ask my "silly" questions.

    1. There is no main function. So how does your code get called

    2. In the last I2C Transaction there is no data being put? This may be stalling the bus. I have to study the sensor spec to understand the I2C Transactors. In the meantime can you add a dummy transaction like below when sending FINISH.

        //
        // Place the value to be sent in the data register.
        //
         I2CMasterDataPut(I2C0_BASE, 0x51);
        //
        // Initiate send of data from the master.
        //
         I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
  • I will try that "dummy transaction" now

    Energia is like Arduino.

    You have istead of main, these 2 fuctions. Setup runs only once, Loop is just that, a infinite loop. It's based in "processing" if that helps understand it

    void setup(){

    }

    void loop(){

    }

  • Hum don't know if it was from adding that dummy transaction but now it randomly just flashes a handfull of times and then stops.

    Removed the transaction and still does. Grabed my tiva tm4c123 to check again if the sensor is alright and it is just fine.

    The addition does make the sensor receive change

    I added again Serial.prints (it's UART comunication for debuging) inside the while(I2CMasterBusy(I2C0_BASE)) {}, each one with diferent names to diferentiate. And also added after them and inside the error checks. 

    There's 1 or 2 busys here and there. and there's an error sometimes. and it's the last one

  • Hello Luois,

    The sensor is a 5V sensor. The TM4C129 is a 3.3V device, so you may want to take care of the fact that the TM4C129 does not have 5V tolerant IO's and you may be damaging the IO's (not immediately) but in the long run if the Pull Up is connected to 5V.

    If the pull up is connected to 3.3V then the sensory may not be working properly.

    Since there is some activity here, I would suggest removing

        //
        // Check for errors.
        //
        if( I2CMasterErr(I2C0_BASE) != I2C_MASTER_ERR_NONE)
        {
            return 0;
        }
        //
        // Initiate send of data from the master.
        //
         I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
        //
        // Wait until master module is done transferring.
        //
    while(I2CMasterBusy(I2C0_BASE)) {}

    and replacing

         I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);

    with

         I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);

    Regards

    Amit

  • Realy? the tm4c129 isn't 5V tolerant like the the tm4c123? well then... i got to change my wiring then.

    Gona try that sugestion code

  • Sincerely i think i'll give up on this API and go back to the drawing board. That or use the sensorlib wich also alows me alot of flexibility and low level access.

    Still this is weird since this works like a charm in stelaris and lm4c123

    Also, tested with Wire library of Energia and it worked with now pull-ups of 3.3V. 

  • So i testing a bit with the i2c FIFO

    Could you please tell how to use I2CFIFOStatus(); to check 

    I2C_FIFO_RX_BELOW_TRIG_LEVEL, I2C_FIFO_RX_FULL, I2C_FIFO_RX_EMPTY,
    I2C_FIFO_TX_BELOW_TRIG_LEVEL, I2C_FIFO_TX_FULL, and I2C_FIFO_TX_EMPTY.

    I think i'm on to sometigh but it's still with a bad practice since i don't wait for the fifo, so i have to clear it wenever I2CFIFODataPutNonBlocking() returns 0;

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <inttypes.h>
    #include "wiring_private.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_i2c.h"
    #include "driverlib/gpio.h"
    #include "driverlib/debug.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/i2c.h"
    #include "driverlib/SysTick.c"
    
    
    #define SLAVE_ADDRESS 0x71
    
    void setup()
    {
      // SysTickbegin();
      Serial.begin(9600);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
      GPIOPinConfigure(GPIO_PB2_I2C0SCL);
      GPIOPinConfigure(GPIO_PB3_I2C0SDA);
      GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
      GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
    
      I2CTxFIFOConfigSet(I2C0_BASE,I2C_FIFO_CFG_TX_MASTER);
      I2CRxFIFOConfigSet(I2C0_BASE,I2C_FIFO_CFG_TX_MASTER);
    
    
      I2CMasterInitExpClk(I2C0_BASE, F_CPU, false);
    
    }
    
    void loop()
    {
      // put your main code here, to run repeatedly:
      Serial.println("call send");
      while(!send()){
        Serial.println("fail");
      delay(5);
      }
      //send();
    //  receive();
      delay(100);
    
    }
    
    int send()
    {
    
      while( I2CMasterBusy(I2C0_BASE))
      {
        Serial.println(" busy1");
      };
      
      I2CMasterSlaveAddrSet(I2C0_BASE, 0x71, false);
      //SEND CONTROL CMD
      if(!I2CFIFODataPutNonBlocking(I2C0_BASE, 0x00)){
         I2CTxFIFOFlush(I2C0_BASE);
        Serial.println("FIFO full 1");
        return 0;
      }
      Serial.println("first sent");
      I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_START);
      
      while(I2CMasterBusy(I2C0_BASE))
      { 
        Serial.println(" busy2");
      }    
      if( I2CMasterErr(I2C0_BASE) != I2C_MASTER_ERR_NONE)
      {
        I2CMasterControl(I2C0_BASE,I2C_MASTER_CMD_FIFO_BURST_SEND_ERROR_STOP);  
        Serial.println("Error1");
        return 0;
      }  
      //FINISH
      if(!I2CFIFODataPutNonBlocking(I2C0_BASE, 0x51)){
        Serial.println("FIFO full 2");
        I2CTxFIFOFlush(I2C0_BASE);
        return 0;
      }
      Serial.println("last sent");
      I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_FINISH);
      while(I2CMasterBusy(I2C0_BASE))
      { 
        Serial.println(" busy3");
      }  
      if( I2CMasterErr(I2C0_BASE) != I2C_MASTER_ERR_NONE)
      {
        I2CMasterControl(I2C0_BASE,I2C_MASTER_CMD_FIFO_BURST_SEND_ERROR_STOP);
        Serial.println("Error2");
        return 0;
      } 
      
      Serial.println("done send ");
      return 1;
    
    }
    
    
    
    
  • Hello Luois,

    The function I2CFIFOStatus returns the status of the I2C FIFO Status register. To check for the conditions you need to logically OR the same with the return value of the function.

    Regards

    Amit

  • So sometigh lke this?

    if( I2CFIFOStatus(I2C0_BASE) | I2C_FIFO_TX_FULL ==  I2C_FIFO_TX_FULL){

    }

  • Hello Luois,

    No. But more like. Remember that you are checking for specific conditions. So if more than one condition were to be fired then the statement would not be true.

    if( I(2CFIFOStatus(I2C0_BASE) & I2C_FIFO_TX_FULL) ==  I2C_FIFO_TX_FULL){

    }

    Regards

    Amit

  • aaaaaaah, that actualy makes more sense since it isolates the bits. Thanks! Going to try it now. Later i will use the osciloscope to assist me in checking the problems

  • So here is what i got so far. The code get's stuck for some reason. its comentated where

    For some reason after transimission the Burst counter just doesn't work, well it works, i check it going down from 2 to 1 everytime but then istead of going to 0 it goes to 2 the second time arround

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <inttypes.h>
    #include "wiring_private.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_i2c.h"
    #include "driverlib/gpio.h"
    #include "driverlib/debug.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/i2c.h"
    #include "driverlib/SysTick.c"
    
    #define SLAVE_ADDRESS 0x71
    
    void setup()
    {  
    
      // SysTickbegin();
      Serial.begin(9600);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
      GPIOPinConfigure(GPIO_PB2_I2C0SCL);
      GPIOPinConfigure(GPIO_PB3_I2C0SDA);
      GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
      GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
    
      I2CTxFIFOConfigSet(I2C0_BASE,I2C_FIFO_CFG_TX_MASTER);
      I2CRxFIFOConfigSet(I2C0_BASE,I2C_FIFO_CFG_RX_MASTER);
    
    
      I2CMasterInitExpClk(I2C0_BASE, F_CPU, false);
    
    }
    
    void loop()
    {
      // put your main code here, to run repeatedly:
      Serial.println("call send");
      while(!send()){
        Serial.println("fail");
        delay(5);
      }
      //send()
      delay(500);
    
    
      //receive();
    
    }
    
    int send()
    {
      while(!(I2CFIFOStatus(I2C0_BASE) & I2C_FIFO_TX_EMPTY));
      while( I2CMasterBusy(I2C0_BASE));
    
    
      I2CMasterSlaveAddrSet(I2C0_BASE, 0x71, false);
    
      I2CMasterBurstLengthSet(I2C0_BASE,2); 
      I2CFIFODataPut(I2C0_BASE, 0x00);
      I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_START);
    
      while( !(I2CFIFOStatus(I2C0_BASE) & I2C_FIFO_TX_EMPTY));  
      while(I2CMasterBusy(I2C0_BASE));
      if( I2CMasterErr(I2C0_BASE) != I2C_MASTER_ERR_NONE)
      {
        I2CMasterControl(I2C0_BASE,I2C_MASTER_CMD_FIFO_BURST_SEND_ERROR_STOP);  
        Serial.println("Error1");
        return 0;
      }  
    
    
      I2CFIFODataPut(I2C0_BASE, 0x51);
    
      while( !(I2CFIFOStatus(I2C0_BASE) & I2C_FIFO_TX_EMPTY));  
      while(I2CMasterBusy(I2C0_BASE)); 
      if( I2CMasterErr(I2C0_BASE) != I2C_MASTER_ERR_NONE)
      {
        I2CMasterControl(I2C0_BASE,I2C_MASTER_CMD_FIFO_BURST_SEND_ERROR_STOP);  
        Serial.println("Error2");
        return 0;
      }    
    
    
      I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_FIFO_BURST_SEND_FINISH);
    
    
      while(!(I2CFIFOStatus(I2C0_BASE) & I2C_FIFO_TX_EMPTY));
    // here I2CMasterBurstCountGet returns 2 while(I2CMasterBusy(I2C0_BASE)); // <---------------Code gets stuck here after 1 sucesseful sent if( I2CMasterErr(I2C0_BASE) != I2C_MASTER_ERR_NONE) { I2CMasterControl(I2C0_BASE,I2C_MASTER_CMD_FIFO_BURST_SEND_ERROR_STOP); Serial.println("Error3"); return 0; } Serial.println("done send "); return 1; }

  • There is a known errata with using I2CMasterErr() -- it tries to get the status from I2CMCS but the tm4c1294ncpdt at least will reset the ADRACK and DATACK bits when BUSY gets reset, so you need to read from I2CMRIS. Forum search has more information.

    That forum search also turns up a hint that you want to be sure BUSY is 1 before entering the loop where you wait for it to go back to 0.

    By the way, yes, this means it is not possible to just run code that worked fine on the lm4c123.

  • Thanks alot for the info.

    So i added a if to check for BUSY before the whiles that wait for it to go 0.

    Removed the error check, still havent corrected it, only removed for a bit of testing.

    Now the code still has the same problem, altough it send much more sucesseful transmitions. Still, i still the the burst counter error, each 2 transmitions the counter is 2 istead of 0 by the end of the transmition

  • Hello Luois,

    In the original code you are waiting for the TXFE flag. Once the Flag indicates that the TX FIFO is empty, the Stop condition also gets put. Hence the code gets stuck in the I2CMasterBusy Status. What you should be doing is to use the STOP condition check.

    Secondly, the FIFO is meant for UDMA mode (though does not restrict the CPU mode), for efficient data transfer w/o CPU intervention. If the application still demands the CPU to be used, then the legacy model is preferred.

    Thirdly, on completion of transfer using BLEN register, the counter must have the value 0, but as you mentioned you see the value 2, I would want to know when do you read it. Also do you read it through the debugger?

    Regards

    Amit

  • Luois Afonso said:
    So i added a if to check for BUSY before the whiles that wait for it to go 0.

    That isn't right, if I understand your code just from what you said.

    Search the forum. You want 2 while() loops like this:

    while (BUSY == 0) { /*do nothing*/ };
    while (BUSY == 1) { /*do nothing*/ };
  • Hello David,

    In this case the use of while loop would be problematic. Since the poster is checking for the TXFE condition first, the Busy signal may go away causing the signal to get stuck in the first while loop.

    Regards

    Amit

  • Just remembered this post.

    For reference, my biggest problem was needing a SysCtlDelay() before checking for a masterbusy. Like here is stated http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/368493.aspx

    After my original code, since i wasn't able to find the problem i tried lost of things, some of which weren't very correct, like Amit stated (i wasn't very good with Tiva at the time)

    I hope this helps other people that have the same problem and find this post