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.

TMS320F28069: I2C Write Read over run problem

Part Number: TMS320F28069


Hi, I am using I2C on TMS320F28069 to write and read multiple devices e.g. I2C to One Wire Bridge, I2C to IO Expander etc. I want to Write and Read as follows.

S AD,Wr [A] WCFG [A] CF [A] Sr AD, Rd, [A] [CF] A\ P

// [ ] indicates from slave

//WCFG  - Write config register address

// CF - configuration byte to write

// AD - Address

// Sr - Repeat Start

When I write alone with out Rd i.e. 

S AD,Wr [A] WCFG [A] CF [A] A\ P

The data sent out on SDA is perfect

but when I do 

S AD,Wr [A] WCFG [A] CF [A] Sr AD, Rd, [A] [CF] A\ P

The read after write over writes the I2caRegs.I2CDXR register. I tried putting delay in between Write and then Read. It simply is sort of ignored and the over right continues. Plz give some idea or pointers on what to check.

The code is 

void I2CAInit(void){

// Initialize I2C
I2caRegs.I2CSAR = 0x0050;
I2caRegs.I2CPSC.all = 10; // Prescaler - need 7-12 Mhz on module clk,Here = 30M/(6+1) = 4.28 Mhz
I2caRegs.I2CCLKL = 10; // Specify Space, must be non zero
I2caRegs.I2CCLKH = 10; // Specify Mark, must be non zero
I2caRegs.I2CIER.all = 0x24; // Enable SCD & ARDY interrupts
I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset
// Stop I2C when suspended
I2caRegs.I2CFFTX.all = 0x6021; // Enable FIFO mode and TXFIFO
I2caRegs.I2CFFTX.bit.TXFFIENA = 1;
I2caRegs.I2CFFRX.all = 0x2040; // Enable RXFIFO, clear RXFFINT

//I2caRegs.I2CFFTX.all = 0x0000; // Disable FIFO mode and TXFIFO
//I2caRegs.I2CFFRX.all = 0x0000; // Disable RXFIFO, clear RXFFINT,
return;
}

int16 B1WWrConfig(Uint16 Config){
// Write configuration (Case A)
// S AD,0 [A] WCFG [A] CF [A] Sr AD,1 [A] [CF] A\ P
// [] indicates from slave
// CF configuration byte to write

I2C.MsgBuffer[0]=B1W_WCFG;
I2C.MsgBuffer[1]=Config;
I2C.NumOfBytes=2; //Number of data bytes, Address not included
I2CAWrite(&I2C);
msec(100);
I2C.MsgStatus = I2C_MSGSTAT_RESTART;
I2C.NumOfBytes=1;
I2CARead(&I2C);
msec(5);
if((I2C.MsgBufferRx[0] == (Config&0x0F) ))return(0);
else return(-1);
}


Uint16 I2CAWrite(I2CMSG *msg){
Uint16 i;
// Wait until the STP bit is cleared from any previous master communication.
// Clearing of this bit by the module is delayed until after the SCD bit is
// set. If this bit is not checked prior to initiating a new message, the
// I2C could get confused.
//if (I2caRegs.I2CMDR.bit.STP == 1)
// return I2C_STP_NOT_READY_ERROR;
while(I2caRegs.I2CMDR.bit.STP);
msg->WrDone = 1;
I2caRegs.I2CSAR = msg->SlaveAddress;

// Check if bus busy
if (I2caRegs.I2CSTR.bit.BB == 1)return I2C_BUS_BUSY_ERROR;
I2caRegs.I2CCNT = msg->NumOfBytes;
I2caRegs.I2CFFTX.bit.TXFFIL = msg->NumOfBytes;
for (i=0; i<msg->NumOfBytes; i++){
I2caRegs.I2CDXR = *(msg->MsgBuffer+i);
}
// Send start as master transmitter
if(msg->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP){

}
//I2caRegs.I2CMDR.all = 0x6E20; //Run Free, Sent Start,Stop,Master Mode, Transmit mode, Module enabled
I2caRegs.I2CMDR.all = 0x6E20; //Run Free, Sent Start,Stop,Master Mode, Transmit mode, Module enabled
//I2caRegs.I2CMDR.bit.RM=1; // Repeat mode
//I2caRegs.I2CMDR.bit.STP=1;
//while(I2caRegs.I2CSTR.bit.XRDY == 1){}
//while(I2caRegs.I2CSTR.bit.BB == 1){}
//while(msg->WrDone);
return I2C_SUCCESS;
}

Uint16 I2CARead(I2CMSG *msg){
// Wait until the STP bit is cleared from any previous master communication.
// Clearing of this bit by the module is delayed until after the SCD bit is
// set. If this bit is not checked prior to initiating a new message, the
// I2C could get confused.
//if (I2caRegs.I2CMDR.bit.STP == 1)
// return I2C_STP_NOT_READY_ERROR;
while(I2caRegs.I2CMDR.bit.STP);
I2caRegs.I2CSAR = msg->SlaveAddress;
msg->RdDone=1;
if(msg->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP){
// Check if bus busy
if (I2caRegs.I2CSTR.bit.BB == 1)return I2C_BUS_BUSY_ERROR;
I2caRegs.I2CCNT = msg->NumOfBytes;
I2caRegs.I2CDXR = 0;
I2caRegs.I2CMDR.all = 0x2620; // Send data to setup EEPROM address
}
else if(msg->MsgStatus == I2C_MSGSTAT_RESTART){
I2caRegs.I2CCNT = msg->NumOfBytes; // Setup how many bytes to expect
I2caRegs.I2CDXR = 0;
I2caRegs.I2CMDR.all = 0x2C20; // Send restart as master receiver
}
//while(I2caRegs.I2CSTR.bit.BB == 1 || I2caRegs.I2CSTR.bit.XRDY == 0)
//while(I2caRegs.I2CSTR.bit.BB == 1);
//while(I2caRegs.I2CSTR.bit.RRDY ==1);
//while(msg->RdDone);
return I2C_SUCCESS;
}

interrupt void i2c_int1a_isr(void){
Uint16 IntSource, i;

// Read interrupt source
IntSource = I2caRegs.I2CISRC.all;

// Interrupt source = stop condition detected
if(I2caRegs.I2CFFTX.bit.TXFFINT){
I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;
I2C.WrDone=0;
}
if(IntSource == I2C_SCD_ISRC){
// If completed message was writing data, reset msg to inactive state
if (I2C.MsgStatus == I2C_MSGSTAT_WRITE_BUSY){
I2C.MsgStatus = I2C_MSGSTAT_INACTIVE;
}
else {
// If a message receives a NACK during the address setup portion of the
// EEPROM read, the code further below included in the register access ready
// interrupt source code will generate a stop condition. After the stop
// condition is received (here), set the message status to try again.
// User may want to limit the number of retries before generating an error.
if(I2C.MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY){
I2C.MsgStatus = I2C_MSGSTAT_SEND_NOSTOP;
}
// If completed message was reading EEPROM data, reset msg to inactive state
// and read data from FIFO.
else if (I2C.MsgStatus == I2C_MSGSTAT_READ_BUSY){
I2C.MsgStatus = I2C_MSGSTAT_INACTIVE;
for(i=0; i < I2C.NumOfBytes; i++){
I2C.MsgBufferRx[i] = I2caRegs.I2CDRR;
}
}
// Check received data
for(i=0; i < I2C.NumOfBytes; i++){
I2C.MsgBufferRx[i] = I2caRegs.I2CDRR;
}
I2C.RdDone=0;
}
}
// Interrupt source = Register Access Ready
// This interrupt is used to determine when the EEPROM address setup portion of the
// read data communication is complete. Since no stop bit is commanded, this flag
// tells us when the message has been sent instead of the SCD flag. If a NACK is
// received, clear the NACK bit and command a stop. Otherwise, move on to the read
// data portion of the communication.
else if(IntSource == I2C_ARDY_ISRC){
if(I2caRegs.I2CSTR.bit.NACK == 1){
I2caRegs.I2CMDR.bit.STP = 1;
I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
}
else if(I2C.MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY){
I2C.MsgStatus = I2C_MSGSTAT_RESTART;
}
} // end of register access ready

// Enable future I2C (PIE Group 8) interrupts
PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
}

 

  • Jawwad,
    Have you read through this appnote? www.ti.com/.../slva704.pdf. It is the I2C basics. I think that you are probably past this, but in case you find it useful, I have shared it.

    - Have you scoped the bus during both sets of transmissions? Are all ACKs and transitions how you would expect them to be?
    - I am not sure I understand how your DXR register is getting overwritten on a read. The I2C has separate Transmit and receive data buffers, there should not be any data moving between these registers without any CPU intervention.Where in your code do you see the DXR data being overwritten?

    Thanks,
    Mark
  • Thanks Mark.
    Yes I have read this and the app note on I2C TMS320x2802x, 2803x Piccolo Inter-Integrated Circuit (I2C) Module. I am using the base code from I2C EEPROM Example.

    Yes I have checked the Transmission on Scope and its ok will all ACKs. E.g. When I write only and no rd, the scope shows exactly this
    S AD,Wr [A] WCFG [A] CF [A] A\ P

    But when write followed by rd with restart i.e.
    S AD,Wr [A] WCFG [A] CF [A] Sr AD, Rd, [A] [CF] A\ P

    I only get upto WCFG [A] after this I don't see CF rather a 0 on SDA...

    The same happens when i watch I2C registers.

    Any clues ?

    Regards
    Jawwad
  • Hi Mark,
    Thanks for the help.
    I solved the problem. The culprit was
    I2caRegs.I2CDXR = 0;
    in function
    Uint16 I2CARead(I2CMSG *msg);

    That came in from the example I2C EEProm Application where its sets the addresses and that is a write inside the read function. A little confusing.

    But thanks for the help

    Thanks
  • Well, I am glad that you were able to figure it out.

    Please don't hesitate to post questions in the future!