Reply by cs_hobbit March 31, 20062006-03-31
Hello,

I have to read and write a 24LC256 EEPROM using I2C with my C6713.
I've solved to write the first 'write'-sequence to the EEPROM [address
high, address low, data]. Looks correct on my logic analyzer. The
24LC256's datasheet says, I have to do the following after the write:

---------------------------------
Once the Stop condition for a Write
command has been issued from the master, the device
initiates the internally timed write cycle. ACK polling
can be initiated immediately. This involves the master
sending a Start condition, followed by the control byte
for a Write command (R/W = 0). If the device is still
busy with the write cycle, then no ACK will be returned.
If no ACK is returned, the Start bit and control byte must
be resent. If the cycle is complete, then the device will
return the ACK and the master can then proceed with
the next Read or Write command.
---------------------------------

How can I check this ACK ? I use the DSP's I2C in master transitter
mode (so R/W is 0), but I'm not sure how to set I2CCNT. 'spru175' says
that 0 in I2CCNT means 65536. 1 means I have to send one data word,
but I can't (this stalls the DSP). In either way, Bit 1 in I2CSTR
never goes low (NACK), only Bit 2 (ARDY) switches if I see the ACK
from 24LC256 on my logic analyzer. How can I solve this problem ?
Below some parts of my source.

Source description: Some parts of this source where designed using
things found in this group (I2CDELAY, I2CSTART, I2CSEND, I2CSTOP).
The mainloop (for(i=0; i buffer which has to be written to the EEPROM. Data is written byte by
byte. As said above, the first byte (with address) is sent without
any problem. Checking for ARDY instead of NACK breaks the 'wait for
completion' loop as it should be (the logic analyzer shows around 10
start-sequences with NACK, then a start-sequence with ACK, nothing
afterwards, look the the loop is breaked at the right place). So the
first byte should be written to the EEPROM without any problem, but as
the mainloop goes to the next byte, the start sequence sent by
'I2CSTART()' doesn't appear on the logic analyzer and the first
I2CSEND() command (address high) doenst return (I2C_xrdy() never
succeedes).
I think the problem has something to do with I2CCNT=0 in the
completion check, but this may be wrong.

Many thanks for any help,
best regards,
Thomas

#define DELAY_TIME 1000

inline void I2CDELAY(Int it)
{
volatile Int j;
for(j=0; j }

inline void I2CSTART(I2C_Handle hI2C)
{
I2C_start(hI2C);
I2CDELAY(DELAY_TIME);
}

inline void I2CSEND(I2C_Handle hI2C, uchar x)
{
while(!I2C_xrdy(hI2C));
I2C_writeByte(hI2C, x);
I2CDELAY(DELAY_TIME);
}

inline void I2CSTOP(I2C_Handle hI2C)
{
I2C_sendStop(hI2C);
I2CDELAY(DELAY_TIME);
}

void ConfigEEPROM(I2C_Handle hI2C, ushort usLength, bool bSend)
{
I2C_Config Config;

// config i2c registers
Config.i2coar = 0x00000000; // own address
Config.i2cimr = 0x00000000; // interrupt mask
Config.i2ccnt = (Uint32)usLength; // data counter
Config.i2csar = (Uint32)0x51; // slave address

Config.i2cclkl = 15; // clock divider low
Config.i2cclkh = 15; // clock divider high
Config.i2cmdr = // mode
0x00004000 | // run free
0x00000400 | // master mode
(bSend?0x00000200:0x00000000) | // receiver or
transmitter mode
0x00000020; // no reset
Config.i2cpsc = (SYSCLK2/4200000)/4; // prescalar

I2C_config(hI2C, &Config);
}

/**** write sequence below ****/

for(i=0; i {
// open and close is already tested outside the loop,
// but doesn't change anything
hI2C = I2C_open(0x00, I2C_OPEN_RESET);
if(INV==hI2C) return 1;

// set (using I2C_config()):
// I2CCNT = 3
// I2CMDR = 0x4620 (run free, master, transmitter, no reset)
// I2COAR = I2CIMR = 0
// (SYSCLK22.5 MHz, mod clk = 4.2Mhz, mas clk = 400kHz)
// I2CPSC = (112500000/4200000)/4
// I2CCLKL = I2CCLKH = 15
ConfigEEPROM(hI2C, 3, true);

I2CSTART(hI2C);

// >>> the following line doesn't return in the second loop <<<
I2CSEND(hI2C, (uchar)(usAddr>>8));
I2CSEND(hI2C, (uchar)(usAddr&0xff));
I2CSEND(hI2C, *pucDest ++);

I2CSTOP(hI2C);

/**** ack polling (my problem) ****/

// wait for completion
for(;;)
{
// same values as above, except I2CCNT = 0
ConfigEEPROM(hI2C, 0, true);

// send start sequence
I2CSTART(hI2C);

// check 4=ARDY, 2=NACK (break if ACK is received)
// at the moment, only ARDY switches if ACK is triggered
// by the EEPROM (seen on the logic analyzer)
uiStat = I2C_RGETH(hI2C, I2CSTR);
if(!(4 & uiStat))
break;

// maybe send a stop condition here
//I2CSTOP(hI2C);
}

// maybe send a stop condition here
//I2CSTOP(hI2C);

I2C_close(hI2C);
}