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 write in TMS320F28035

Other Parts Discussed in Thread: TMS320F28035

Hi

I am programming the I2C module in the loopback mode for TMS320F28035 and I am facing the following problem -

I am trying to write data, to an EEPROM- AT24C32D (slave addr :0XA0/A1) but, after reading back i saw that only the 1st 4 bytes get written successfully and the remaing bytes read default 0xFF. ( i tried with 10 , 32 bytes )

It is in polling mode and RRDY and  XRDY are the flags.


Can someone please help me on this ?

Please find the code attached



//###########################################################################
//
//!  \addtogroup f2803x_example_list
//!  <h1>I2C EEPROM(i2c_eeprom)</h1>
//!
//!  This program requires an external I2C EEPROM connected to
//!  the I2C bus at address 0x50.
//!  This program will write 1-14 words to EEPROM and read them back.
//!  The data written and the EEPROM address written to are contained
//!  in the message structure, \b I2cMsgOut1. The data read back will be
//!  contained in the message structure \b I2cMsgIn1.
//!  
//!  \note This program will only work on kits that have an on-board I2C EEPROM. T
//!  (e.g. F2803x eZdsp)
//!
//!  \b Watch \b Variables \n
//!  - I2cMsgIn1
//!  - I2cMsgOut1
//
//###########################################################################
// $TI Release: F2803x C/C++ Header Files and Peripheral Examples V127 $
// $Release Date: March 30, 2013 $
//###########################################################################

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File

// Note: I2C Macros used in this example can be found in the
// DSP2803x_I2C_defines.h file

// Prototype statements for functions found within this file.
void   I2CA_Init(void);
Uint16 I2CA_WriteData(struct I2CMSG *msg);
Uint16 I2CA_ReadData(struct I2CMSG *msg);
__interrupt void i2c_int1a_isr(void);
void pass(void);
void fail(void);
void compare_I2C_RW(void);

Uint16 correct=0;

#define I2C_SLAVE_ADDR        0x50
#define I2C_SLAVE_ADDR_READ	  0x51
//#define I2C_NUMBYTES          2
#define I2C_NUMBYTES          	10
#define I2C_EEPROM_HIGH_ADDR  0x00
#define I2C_EEPROM_LOW_ADDR   0x30

// Global variables
// Two bytes will be used for the outgoing address,
// thus only setup 14 bytes maximum
struct I2CMSG I2cMsgOut1={I2C_MSGSTAT_SEND_WITHSTOP,
                          I2C_SLAVE_ADDR,
                          I2C_NUMBYTES,
                          I2C_EEPROM_HIGH_ADDR,
                          I2C_EEPROM_LOW_ADDR,
                          0x12,                   // Msg Byte 1
                          0x34,
                          0x56,
                          0x78,
                          0x06,
                          0x06,
                          0x06,
                          0x06,	                  // Msg Byte 2
                          0x06,
                          0x06};

struct I2CMSG I2cMsgIn1={ I2C_MSGSTAT_SEND_NOSTOP,
                          I2C_SLAVE_ADDR,
                          I2C_NUMBYTES,
                          I2C_EEPROM_HIGH_ADDR,
                          I2C_EEPROM_LOW_ADDR};

struct I2CMSG *CurrentMsgPtr;				// Used in interrupts
Uint16 PassCount;
Uint16 FailCount;
Uint16 GlobalCount=0;
void main(void)
{
   Uint16 Error;
   Uint16 i;

   CurrentMsgPtr = &I2cMsgOut1;

// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2803x_SysCtrl.c file.
   InitSysCtrl();

// Step 2. Initialize GPIO:
// This example function is found in the DSP2803x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio();
// Setup only the GP I/O only for I2C functionality
   InitI2CGpio();

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
   DINT;

// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2803x_PieCtrl.c file.
   InitPieCtrl();

// Disable CPU interrupts and clear all CPU interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in DSP2803x_DefaultIsr.c.
// This function is found in DSP2803x_PieVect.c.
   InitPieVectTable();

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
   EALLOW;	// This is needed to write to EALLOW protected registers
 //  PieVectTable.I2CINT1A = &i2c_int1a_isr;
   EDIS;   // This is needed to disable write to EALLOW protected registers

// Step 4. Initialize all the Device Peripherals:
// This function is found in DSP2803x_InitPeripherals.c
// InitPeripherals(); // Not required for this example
   I2CA_Init();

   for (i = 0; i < I2C_MAX_BUFFER_SIZE; i++)
     {
         I2cMsgIn1.MsgBuffer[i] = 0x0000;
     }
   I2CA_WriteData(&I2cMsgOut1);
   CurrentMsgPtr = &I2cMsgIn1;
   I2CA_ReadData(&I2cMsgIn1);
   compare_I2C_RW();
}

// Step 5. User specific code

Uint16 I2CA_WriteData(struct I2CMSG *msg)
   {
	Uint16 i=0;
	//I2caRegs.I2CMDR.all = 0x2620;//Start condition, Master transmitter, 7 bit addr, nonrepeat mode


	      // Setup slave address
	   I2caRegs.I2CSAR = msg->SlaveAddress;
	   I2caRegs.I2CMDR.all = 0x2E20;//Start condition, Master transmitter, 7 bit addr, nonrepeat mode
	  
	   I2caRegs.I2CCNT = msg->NumOfBytes+2;
	  	
	  	  I2caRegs.I2CDXR = msg->MemoryHighAddr;
	  
	   while(!(I2caRegs.I2CSTR.bit.XRDY));
	   I2caRegs.I2CDXR = msg->MemoryLowAddr;
	   while(!(I2caRegs.I2CSTR.bit.XRDY));
	   	   for (i=0; i<msg->NumOfBytes; i++)
	   {
	   		//while(!(I2caRegs.I2CSTR.bit.XRDY))

	      I2caRegs.I2CDXR = *(msg->MsgBuffer+i);
	      while(!(I2caRegs.I2CSTR.bit.XRDY));
	   }
	    

	      // Send start as master transmitter, free running with breakpoint, IRS=1,STP=1,STT=1,NACKMODE=0,MST=1,TRX=1,FREE=1,STB=1

	   
	   return I2C_SUCCESS;
	}


Uint16 I2CA_ReadData(struct I2CMSG *msg)
{
	Uint16 i=0;
	 I2caRegs.I2CSAR = msg->SlaveAddress;
	 I2caRegs.I2CMDR.all = 0x2620;//Start condition, Master transmitter, 7 bit addr, nonrepeat mode
	 I2caRegs.I2CCNT = 2;
	  I2caRegs.I2CDXR = msg->MemoryHighAddr;
		  //	I2caRegs.I2CSTR.bit.XRDY=1;
		   while(!(I2caRegs.I2CSTR.bit.XRDY));
		   I2caRegs.I2CDXR = msg->MemoryLowAddr;
		   while(!(I2caRegs.I2CSTR.bit.XRDY));
		   I2caRegs.I2CSAR = msg->SlaveAddress;
		    I2caRegs.I2CMDR.all=0x2C20;
		    I2caRegs.I2CCNT=msg->NumOfBytes;

	 for (i=0; i<msg->NumOfBytes; i++)
	 	   {
	 	   		 	   			;
	 	   		while(!(I2caRegs.I2CSTR.bit.RRDY));
	 	        *(msg->MsgBuffer+i)=I2caRegs.I2CDRR;

	 	   }

   return I2C_SUCCESS;
}



void I2CA_Init(void)
{
   
   I2caRegs.I2CPSC.all = 6;		    // Prescaler - need 7-12 Mhz on module clk
   I2caRegs.I2CCLKL = 10;			// NOTE: must be non zero
   I2caRegs.I2CCLKH = 5;			// NOTE: must be non zero
   //I2caRegs.I2CIER.all = 0x24;		// Enable SCD & ARDY interrupts
   I2caRegs.I2CMDR.all = 0;
  I2caRegs.I2CMDR.all = 0x0020;	// Take I2C out of reset
   return;
}


void compare_I2C_RW()
{
	Uint16 i;
	//Uint16 correct=0;

	for(i=0;i<I2C_NUMBYTES;i++)
	{
		if(I2cMsgOut1.MsgBuffer[i]==I2cMsgIn1.MsgBuffer[i])
		{
			correct++;
		}
	}

}

  • Hi Smita,

    Is there any particular reason why you're using an external EEPROM when you can emulate the same on the chip's flash sector?
    Coming to the point, if you want to send multiple data you have to check the status of the Tx shift register before writing the next byte to I2CDRR. Same setup as before, then

    for(i=0; i<N ;i++){

    while(I2caRegs.I2CSTR.bit.XRDY == 0){}; //Do nothing till bus is free
    I2caRegs.I2CDXR = data[i]; //Next data byte

    }

     

    Alternatively, you can set it up in FIFO mode, where you can write 4 data points to the fifo and then transmit. Here's an example

    I2caRegs.I2CSAR = I2C_SLAVE_ADDR; //Set slave address
       I2caRegs.I2CCNT = I2C_NUMBYTES; //Numbe rof bytes to transfer
       I2caRegs.I2CFFTX.all = 0x6000; //enable FIFO mode and reset TX FIFO
       I2caRegs.I2CDXR = data[0] //Send data[0-3]
       I2caRegs.I2CDXR = data[1] //Store in next FIFO level
       I2caRegs.I2CDXR = data[2] //Store in next FIFO level
       I2caRegs.I2CDXR = data[3] //Store in next FIFO level
       I2caRegs.I2CMDR.bit.TRX = 1; //Set to Transmit mode
       I2caRegs.I2CMDR.bit.MST = 1; //Set to Master mode
       I2caRegs.I2CMDR.bit.FREE = 1;//Run in FREE mode
       I2caRegs.I2CMDR.bit.STP = 1; // release the bus after Tx
       I2caRegs.I2CMDR.bit.STT = 1; //Send the start bit, transmission will follow

    You can reload the FIFO after this for the next 4 bytes and so on

    Hope this helps!

    Regards,

    Gautam

  • Hi Gautam

    Thank you very much for the reply. Sorry I did not reply immediately ,as I was out of town for official purpose.

    Regarding your question about using EEPROM, and not chip's flash sector, is because, the data we are writing are fault condition parameters. There are many such parameters for us to store and the flash area is not enough for us to store these parameters along with the code.

    The code that was posted had the1st suggestion you had given - which is polling the XRDY bit and the problem I reported, was using this method.

    I am not sure how the FIFO mode would help me. In the non FIFO mode, do you have any suggestion?

     

    Thanks & Regards

    Smita

  • No problem, for the late reply.

    Regarding your question about using EEPROM, and not chip's flash sector, is because, the data we are writing are fault condition parameters. There are many such parameters for us to store and the flash area is not enough for us to store these parameters along with the code.

    That's a whole lot of data! Just for your info:

    So if you emulate Sector H as an EEPROM; you can calculate how much memory you can avail.

    for(i=0; i<N ;i++){
    
    while(I2caRegs.I2CSTR.bit.XRDY == 0){}; //Do nothing till bus is free
    I2caRegs.I2CDXR = data[i]; //Next data byte
    
    }

    So, the above code is not working for more than 4bytes, right? Do check the I2C configuration for any improper initializations. Also, did you check with any limitations on the EEPROM side (datasheet) coz the above routine is well tested.

    Regards,

    Gautam

  • Thank you Gautam

    I will get back to you, once I complete it

    Thanks & Regards

    Smita

  • EEPROM take time to complete write operation, typical 5-10ms. So wait at least 10ms before trying another write. Normally chip won't respond to any commands during write cycle.

    Flash emulation is OK for few times write, say 1-100 in whole life, so no comparison with normal EEPROM.

    Flash erase only in sectors (4K-8K etc), erase time typically 5-10 seconds, So not practical for regular saving of data.

  • Thanks Joy, for sharing your opinion. Very helpful tips!

    Regards,

    Gautam

  • Hi Gautam and Joy

    Last week We tried givng a delay of around 50ms between write and read operation on the EEPROM and it worked.

    The twr spec for the EEPROM was something which i did not see and it was not working.

    Back then The max spec mentioned was 5ms and hence i did not worry too much about it.

    Thank you very much for your inputs

    Thanks & Regards

    Smita

  • That's great Smita.

    Good luck & Regards,

    Gautam