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.

Not able to Set the Run Bit in I2C

i have written a program to scan the I2C Devices present in my board.i debugged and found that for enabling STRAT,STOP and RUN bit in I2C control\status register i am assigning 0x07 but the register is always written with 0x06.the program is as below:-

//Header Files
#include <stdint.h>

//Macros to define the Base Address of I2C Registers
#define I2C_RUN_MODE_GATE_CONTROL_REG_BASE_ADDR     0x400FE620
#define I2C0_MASTER_CONFIG_REG_BASE_ADDR             0x40020020
#define I2C0_MASTER_TIME_PERIOD_REG_BASE_ADDR         0x4002000C
#define I2C0_MASTER_SLAVE_ADDR_REG_BASE_ADDR         0x40020000
#define I2C0_MASTER_DATA_REG_BASE_ADDR                 0x40020008
#define I2C0_MASTER_CONTROL_STATUS_REG_BASE_ADDR     0x40020004
#define I2C0_PERIPHERAL_READY_REG_BASE_ADDR         0x400FEA20

//Macros to define the Base Address of GPIO Registers
#define GPIO_RUN_MODE_GATE_CONTROL_REG_BASE_ADDR     0x400FE608
#define GPIO_PORTB_ALT_FUN_SELECT_REG_BASE_ADDR      0x40059420
#define GPIO_PORTB_CTRL_REG_BASE_ADDR                   0x4005952C
#define GPIO_PORTB_DIR_REG_BASE_ADDR                   0x40059400
#define GPIO_PORTB_DEN_REG_BASE_ADDR                   0x4005951C
#define GPIO_PORTB_OPEN_DRAIN_SELECT_REG_BASE_ADDR  0x4005950C
#define GPIO_PORTB_PULLUP_SELECT_REG_BASE_ADDR      0x40059510
#define GPIO_PERIPHERAL_READY_REG_BASE_ADDR         0x400FEA08

//Macros for constands
#define MAX_SLAVE_ADDR             127

//Function Declarations
void IniializeI2C(void);
void ScanDeviceForI2C0(void);

int main(void) {
    //Initialize I2C0 and configure as Master
    IniializeI2C();
    //scan for all I2C Devices connected with I2C Bus 0
    ScanDeviceForI2C0();

return 0;
}

//this will initialize I2C Module for Tx and Rx
void IniializeI2C(void)
{
    //Enable and Supply clock to the I2C 0 Module
    (*((volatile uint32_t *)(I2C_RUN_MODE_GATE_CONTROL_REG_BASE_ADDR)))|=0x00000001;
    //Wait Until I2C0 module is ready for use
    while(!((*((volatile uint32_t *)(I2C0_PERIPHERAL_READY_REG_BASE_ADDR))) & (0x01)));


    //Enable and supply clock to the GPIO PORTB which will use as SDA and SCL line for I2C 0 Module
    (*((volatile uint32_t *)(GPIO_RUN_MODE_GATE_CONTROL_REG_BASE_ADDR)))|=0x00000002;
    //Wait Until GPIO PORT B module is ready for use
    while(!((*((volatile uint32_t *)(GPIO_PERIPHERAL_READY_REG_BASE_ADDR))) & (0x02)));


    //Configure GPIO PORTB PIN2 and PIN3 as Alternate Function Pin
    (*((volatile uint32_t *)(GPIO_PORTB_ALT_FUN_SELECT_REG_BASE_ADDR)))=0x0000000C;

    //Enable I2C 0 SDA pin for open drain configuration
    (*((volatile uint32_t *)(GPIO_PORTB_OPEN_DRAIN_SELECT_REG_BASE_ADDR)))|=0x00000008;

    //Configure the PORTB PIN2 for I2C 0 SCL Line and PORTB PIN 3 for I2C 0 SDA Line
    (*((volatile uint32_t *)(GPIO_PORTB_CTRL_REG_BASE_ADDR)))=0x00002200;

    //Configure PORTB PIN2 AS Output PIN3 as output
    (*((volatile uint32_t *)(GPIO_PORTB_DIR_REG_BASE_ADDR)))=0x0000000C;

    //configure PORTB PIN2 AND PIN3 as Digital enable
    (*((volatile uint32_t *)(GPIO_PORTB_DEN_REG_BASE_ADDR)))=0x0000000C;

     //Select GPIO PORTB Pullup registers for PIN2 and PIN3
    (*((volatile uint32_t *)(GPIO_PORTB_PULLUP_SELECT_REG_BASE_ADDR)))|=0x0000000C;

    //Configure I2C0 as Master
    (*((volatile uint32_t *)(I2C0_MASTER_CONFIG_REG_BASE_ADDR)))|=0x00000010;

    //set SCL clock speed of 100 kbps
    (*((volatile uint32_t *)(I2C0_MASTER_TIME_PERIOD_REG_BASE_ADDR)))|=0x07;
}

//Scan for I2C devices connected with I2C0
void ScanDeviceForI2C0(void)
{
    int index=0;
    //scan for each I2C device present in I2C0 Bus
    for(index=0;index<MAX_SLAVE_ADDR;index++)
    {
        //specify the address of the Slave
        (*((volatile uint32_t *)(I2C0_MASTER_SLAVE_ADDR_REG_BASE_ADDR)))=(index<<1);

        //specify the  mode as Receive
        (*((volatile uint32_t *)(I2C0_MASTER_SLAVE_ADDR_REG_BASE_ADDR)))|=0x01;

        //enable START,STOP and RUN bit
        (*((volatile uint32_t *)(I2C0_MASTER_CONTROL_STATUS_REG_BASE_ADDR)))|=0x07;

        //wait until BUS became free
        while((*((volatile uint32_t *)(I2C0_MASTER_CONTROL_STATUS_REG_BASE_ADDR))) & (0x40));

        //check the error bit to determine whether slave address was acknowledged or not
        if(!((*((volatile uint32_t *)(I2C0_MASTER_CONTROL_STATUS_REG_BASE_ADDR)))&(0x02)))
        {
            //slave address was acknowledged
          
        }
    }
}

can anybody please tell me the reason behind it?

Thanks,

Jeke.

  • Hi Jeke,

         If you don't know yet, there are Tivaware C API's for I2C. See, details at Tivaware Peripheral Driver Library Users Guide doc.

    - kel

  • Hi Kel,

    actually i wanted learn from scratch therefore i tried to implement by going through the Data Sheet.i follow the same steps that has been mentioned there but,still the Run Bit is not setting.


    Can you please help on this?

    Thanks,

    Jeke.

  • Hello Jeke

    I will second Kel's recommendation. The idea first would be to get it working with TivaWare to weed out any hardware issue before moving to the Direct Macro Access.

    As an example, when the MCS is written with 0x7, you cannot read it back to get the status of the START+STOP+RUN bit. The read shall return the Status of the transaction which in this case means both Address and Data where NACK.

    Regards

    Amit

  • Hi Amit,

    Thanks for your info.

    But what i observed that when i am reading MCS register to check for BUSBUSY flag the error flag is getting cleared.that's why after that when i am checking for ERROR flag its coming as always 0.is there any other way to check whethre ERROR flag is set or not?

    Thanks,

    Jeke.

  • Hello Jeke,

    The Error flag is clear on read. Thus when waiting for the Busy Signal to go low, if the flag is set, then it will get cleared as the register is read out. You can use the following code to get the status w/o losing on the error bits.

    ui32Err = 0;

    while((ui32Status = HWREG(ui32Base + I2C_O_MCS)) & I2C_MCS_BUSY)

    {

        if((ui32Status & I2C_MCS_DATACK) == I2C_MCS_DATACK)

        {

            ui32Err = 1;

        }

        if((ui32Status & I2C_MCS_ADRACK) == I2C_MCS_ADRACK)

        {

            ui32Err = 2;

        }

    }

    Regards

    Amit

  • Hi Amit,

    i tried the same as u mentioned but its not going at all inside the while loop.


    Thanks,

    Jeke.

  • Hello Jeke

    If you are single stepping then it will be over before the single step can be done, since the moment you write the RUN bit I2C would have transmitted the frame. What I would suggest is to scope the I2C Frame along with the BUSY flag, i.e. before the while loop is called, set a GPIO high and after the while loop ends, set the GPIO low. If the GPIO remains high for the duration of the I2C Frame, then the while loop is working fine. Add another GPIO toggle for the error condition detection and then plot the SCL, SDA, BUSY-GPIO and ERR-GPIO on a scope plot to see if it is working as expected.

    Do this with the Memory Browser or Register View in CCS closed.

    Regards

    Amit

  • Jeke kumar Gochhayat said:
    scan the I2C Devices...my board...debugged and found "I2C Control\Status" register...is always written with 0x06

    Much back/forth here - and never does poster report the result of letting his program, "RUN to completion!"  By running the program - much (all?) of the effort here would have been saved.

    Poster's desire to learn - use of Direct Register and manual entry of long, complex Register Addresses - which "fly in the face of far easier APIs" - proves NOT the best means to learn...

    Use of API's remains the best "learning mechanism" for 99% here.  (surely includes this reporter...)